video: tegra: add device tree support for DC
Min-wuk Lee [Tue, 30 Apr 2013 14:11:25 +0000 (23:11 +0900)]
Add device tree support for display controller.
This change is for Tegra114 only.

Bug 1240921

Change-Id: I28ddc2e3b9a9a818ebc330dcf90ee879420726ab
Signed-off-by: Min-wuk Lee <mlee@nvidia.com>
Reviewed-on: http://git-master/r/240006
(cherry picked from commit d27e77cadf76c4c38f12f476ad6c678b227ef8c4)
Reviewed-on: http://git-master/r/289667
Reviewed-by: Automatic_Commit_Validation_User
Reviewed-by: Gabby Lee <galee@nvidia.com>
Tested-by: Gabby Lee <galee@nvidia.com>

12 files changed:
Documentation/devicetree/bindings/video/nvidia,tegra114-dc.txt [new file with mode: 0644]
Documentation/devicetree/bindings/video/nvidia,tegra114-dsi.txt [new file with mode: 0644]
Documentation/devicetree/bindings/video/nvidia,tegra114-hdmi.txt [new file with mode: 0644]
arch/arm/mach-tegra/include/mach/dc.h
drivers/video/tegra/dc/Makefile
drivers/video/tegra/dc/dc.c
drivers/video/tegra/dc/dc_priv.h
drivers/video/tegra/dc/dsi.c
drivers/video/tegra/dc/hdmi.c
drivers/video/tegra/dc/mipi_cal.c
drivers/video/tegra/dc/mipi_cal.h
drivers/video/tegra/dc/of_dc.c [new file with mode: 0644]

diff --git a/Documentation/devicetree/bindings/video/nvidia,tegra114-dc.txt b/Documentation/devicetree/bindings/video/nvidia,tegra114-dc.txt
new file mode 100644 (file)
index 0000000..0aaba15
--- /dev/null
@@ -0,0 +1,353 @@
+NVIDIA Tegra114 Display Controller
+==================================
+
+1) The dc node:
+ dc node must be contained in host1x parent node. This node represents
+ NVIDIA Tegra114 Display controller.
+
+ Required properties:
+ - name: dc
+ - compatible: Should contain "nvidia,tegra114-dc".
+ - reg: Physical base address and length of the controller's registers.
+ - interrupts: The interrupt outputs from the controller.
+ - nvidia,memory-clients: This is the "swgroup" ID in the Tegra TRM term.
+ - nvidia,dc-flags: This is to enable display controller in probe time.
+   "dc_flag_en" or remove this property (do not set this property).
+ - nvidia,emc-clk-rate: Initially required embedded memory controller clk rate.
+ - nvidia,cmu-enable: Toggle switch for color management unit.
+
+ - Child nodes represent node of modes, output settings, framebuffer data,
+   smart dimmer settings, color management unit settings, dsi output device settings.
+
+1.A) NVIDIA Display Controller Modes
+ This must be contained in dc parent node. This contains supported modes.
+
+ Required properties:
+ - name: Should be "display-timings"
+
+ - Child nodes represent modes. Several modes can be prepared.
+
+1.A.i) NVIDIA Display Controller Mode timing
+ This must be contained in display-timings parent node. This contains mode settings, including
+ display timings.
+
+ Required properties:
+ - name: Can be arbitrary, but each sibling node should have unique name.
+ - hactive, vactive: display resolution.
+ - hfront-porch, hback-porch, hsync-len: horizontal display timing parameters
+   in pixels.
+ - vfront-porch, vback-porch, vsync-len: vertical display timing parameters in
+   lines.
+ - clock-frequency: display clock in Hz.
+ - nvidia,h-ref-to-sync: H reference to HSYNC. This specifies the start position of HSYNC
+   with respect to H reference point.
+ - nvidia,v-ref-to-sync: V reference to VSYNC. This specifies the start position of VSYNC
+   with respect to V reference point.
+
+1.B) NVIDIA Display Controller Default Output Settings
+ This must be contained in dc parent node. This is default output settings.
+
+ Required properties:
+ - name: Should be "dc-default-out".
+ - nvidia,out-type: Output type. Should be "dsi" or "hdmi".
+ - nvidia,out-width: Width in struct fb_var_screeninfo. width of picture in mm.
+ - nvidia,out-height: Height in struct fb_var_screeninfo. height of picture in mm.
+ - nvidia,out-flags: Should be "continuous" or "oneshot" or "hotplug_high" or "hotplug_low"
+   or "continuous_initialized" or "oneshot_initialized"
+ - nvidia,out-parent-clk: Parent clk for display controller.
+ - nvidia,out-max-pixclk: Maximum pixel clock in pico-seconds.
+ - nvidia,out-align: Display data alignment. Should be "msb" or "lsb".
+ - nvidia,out-order: Display data order. Should be "rtob" or "btor".
+
+1.C) NVIDIA Display Controller framebuffer data
+ This must be contained in dc parent node. This is required framebuffer data.
+
+Required properties:
+ - name: Should be "framebuffer-data".
+ - nvidia,fb-bpp: Bits per pixel of fb.
+ - nvidia,fb-flags: Window is updated in display controller device probe. Should be "flip_on_probe",
+   or remove this property (do not set this property).
+ - nvidia,fb-xres: Visible resolution for width.
+ - nvidia,fb-yres: Visible resolution for height.
+
+1.D) NVIDIA Display Controller Smart Dimmer Settings
+ This must be contained in dc parent node. This is smart dimmer settings.
+
+ Required properties:
+ - name: Should be "smartdimmer".
+ - nvidia,use-auto-pwm: With enabled, hardware adjust the backlight PWM control
+   signal directly.
+ - nvidia,hw-update-delay: It determines the delay of the update of the hardware
+   enhancement value (K) that is applied to the pixels.
+ - nvidia,bin-width: Should be written as a string format. It is the width of the
+   histogram bins, in quantisation level. "-1" indicates automatic based on aggressiveness.
+ - nvidia,aggressiveness: The aggressiveness level of the smart dimmer algorithm.
+ - nvidia,use-vid-luma: With enabled, it uses video luminance control of luminance.
+ - nvidia,phase-in-adjustments: Software backlight phase-in
+ - nvidia,k-limit-enable: When enabled, Max.K is taken from K_LIMIT register (nvidia,k-limit)
+   rather than computed from nvidia,aggressiveness.
+ - nvidia,k-limit: When nvidia,k-limit-enable is enabled, limits raw K independently of
+   aggressiveness.
+ - nvidia,sd-window-enable: When enabled, constrain histogram (and therefore backlight)
+   to a rectangular subset of display.
+ - nvidia,soft-clipping-enable: When enabled, enhancement gain (K) is reduced for pixels
+   above nvidia,soft-clipping-threshold level to avoid saturation.
+ - nvidia,soft-clipping-threshold: Threshold at which pixel enhancement gain is reduced.
+ - nvidia,smooth-k-enable: When enabled, max raw K change per frame is limited to
+   nvidia,smooth-k-incr.
+ - nvidia,smooth-k-incr: When nvidia,smooth-k-enable is enabled, the raw K is changed
+   at most by smooth-k-incr per frame.
+ - nvidia,coeff: Luminance calculation coefficients used to convert the red green and
+   blue color components into a luminance value. The conversion is performed according to
+   the following equation: Luminance = (R*R_COEFF + G*G_COEFF + B*B_COEFF) >> 4.
+   Need to write blue, green, red coefficient for luminance calculation in sequence.
+ - nvidia,fc: Flicker control that prevents rapid and frequent changes
+   in the enhancement value. Need to write time_limit, threshold in sequence.
+ - nvidia,blp: Defines the parameters for the backlight temporal response model. Need to
+   write time_constant for the response curve and step that determines the instantaneous
+   portion of the target value of enhancement that is applied: <time_constant, step>.
+ - nvidia,bltf: Backlight transfer function. Each points on the transfer function curve
+   defines how the backlight output changes with respect to the control input. The 17th point
+   is defined to be the maximum value.
+ - nvidia,lut: Enhancement value (K) look up table. each LUT entry contains the value of k
+   for each of the three color components (R_LUT, G_LUT, B_LUT in sequence).
+   There are nine entries in total.
+ - nvidia,use-vpulse2: With enabled, run histogram on vpulse2 rather than vsync.
+ - nvidia,bl-device-name: Backlight device name.
+
+1.E) NVIDIA Display Controller Color Management Unit Settings
+ This must be contained in dc parent node. This is color management unit settings.
+
+ Required properties:
+ - name: Should be "cmu".
+ - nvidia,cmu-csc: CMU color space conversion matrix. It is 3X3 matrix.
+ - nvidia,cmu-lut2: CMU LUT2. Should be 960 u8 arrays.
+
+Example
+       host1x {
+               /* tegradc.0 */
+               dc@54200000 {
+                       compatible = "nvidia,tegra114-dc";
+                       reg = <0x54200000 0x00040000>;
+                       interrupts = <0 73 0x04>;
+                       status = "okay";
+                       nvidia,dc-flags = "dc_flag_en";
+                       nvidia,emc-clk-rate = <204000000>;
+                       nvidia,cmu-enable = <1>;
+                       dc-default-out {
+                               nvidia,out-type = "dsi";
+                               nvidia,out-width = <217>;
+                               nvidia,out-height = <135>;
+                               nvidia,out-flags = "continuous";
+                               nvidia,out-parent-clk = "pll_d_out0";
+                       };
+                       display-timings {
+                               1920p32 {
+                                       clock-frequency = <154700000>;
+                                       hactive = <1920>;
+                                       vactive = <1200>;
+                                       hfront-porch = <120>;
+                                       hback-porch = <32>;
+                                       hsync-len = <16>;
+                                       vfront-porch = <17>;
+                                       vback-porch = <16>;
+                                       vsync-len = <2>;
+                                       nvidia,h-ref-to-sync = <4>;
+                                       nvidia,v-ref-to-sync = <1>;
+                               };
+                       };
+                       framebuffer-data {
+                               nvidia,fb-bpp = <32>; /* bits per pixel */
+                               nvidia,fb-flags = "flip_on_probe";
+                               nvidia,fb-xres = <1920>;
+                               nvidia,fb-yres = <1200>;
+                       };
+                       smartdimmer {
+                               status = "okay";
+                               nvidia,use-auto-pwm = <0>;
+                               nvidia,hw-update-delay = <0>;
+                               nvidia,bin-width = "-1";
+                               nvidia,aggressiveness = <5>;
+                               nvidia,use-vid-luma = <0>;
+                               nvidia,phase-in-settings = <0>;
+                               nvidia,phase-in-adjustments = <0>;
+                               nvidia,k-limit-enable = <1>;
+                               nvidia,k-limit = <200>;
+                               nvidia,sd-window-enable = <0>;
+                               nvidia,soft-clipping-enable= <1>;
+                               nvidia,soft-clipping-threshold = <128>;
+                               nvidia,smooth-k-enable = <1>;
+                               nvidia,smooth-k-incr = <4>;
+                               nvidia,coeff = <5 9 2>;
+                               nvidia,fc = <0 0>;
+                               nvidia,blp = <1024 255>;
+                               nvidia,bltf = <57 65 73 82
+                                                 92 103 114 125
+                                                 138 150 164 178
+                                                 193 208 224 241>;
+                               nvidia,lut = <255 255 255
+                                                199 199 199
+                                                153 153 153
+                                                116 116 116
+                                                85 85 85
+                                                59 59 59
+                                                36 36 36
+                                                17 17 17
+                                                0 0 0>;
+                               nvidia,use-vpulse2 = <1>;
+                               nvidia,bl-device-name = "pwm-backlight";
+                       };
+                       cmu {
+                               nvidia,cmu-csc = < 0x138 0x3Ba 0x00D
+                                                  0x3F5 0x120 0x3E6
+                                                  0x3FE 0x3F8 0x0E9 >;
+                               nvidia,cmu-lut2 = < 0 1 2 3 4 5 6 6
+                                                   7 8 9 10 11 11 12 13
+                                                   13 14 15 15 16 17 17 18
+                                                   18 19 19 20 20 21 21 22
+                                                   22 23 23 23 24 24 24 25
+                                                   25 25 26 26 26 27 27 27
+                                                   28 28 28 28 29 29 29 29
+                                                   30 30 30 30 31 31 31 31
+                                                   32 32 32 32 33 33 33 33
+                                                   34 34 34 35 35 35 35 36
+                                                   36 36 37 37 37 37 38 38
+                                                   38 39 39 39 39 40 40 40
+                                                   41 41 41 41 42 42 42 43
+                                                   43 43 43 44 44 44 45 45
+                                                   45 45 46 46 46 46 47 47
+                                                   47 47 48 48 48 48 49 49
+                                                   49 49 50 50 50 50 50 51
+                                                   51 51 51 52 52 52 52 52
+                                                   53 53 53 53 53 53 54 54
+                                                   54 54 54 55 55 55 55 55
+                                                   55 56 56 56 56 56 56 57
+                                                   57 57 57 57 57 57 58 58
+                                                   58 58 58 58 59 59 59 59
+                                                   59 59 59 60 60 60 60 60
+                                                   60 60 61 61 61 61 61 61
+                                                   61 62 62 62 62 62 62 62
+                                                   63 63 63 63 63 63 63 64
+                                                   64 64 64 64 64 64 65 65
+                                                   65 65 65 65 66 66 66 66
+                                                   66 66 66 67 67 67 67 67
+                                                   67 68 68 68 68 68 68 69
+                                                   69 69 69 69 69 70 70 70
+                                                   70 70 70 71 71 71 71 71
+                                                   71 72 72 72 72 72 72 73
+                                                   73 73 73 73 73 74 74 74
+                                                   74 74 74 74 75 75 75 75
+                                                   75 75 76 76 76 76 76 76
+                                                   77 77 77 77 77 77 77 78
+                                                   78 78 78 78 78 79 79 79
+                                                   79 79 79 79 80 80 80 80
+                                                   80 80 80 80 81 81 81 81
+                                                   81 81 81 82 82 82 82 82
+                                                   82 82 82 83 83 83 83 83
+                                                   83 83 83 83 84 84 84 84
+                                                   84 84 84 84 85 85 85 85
+                                                   85 85 85 85 85 85 86 86
+                                                   86 86 86 86 86 86 86 86
+                                                   87 87 87 87 87 87 87 87
+                                                   87 87 88 88 88 88 88 88
+                                                   88 88 88 88 88 88 89 89
+                                                   89 89 89 89 89 89 89 89
+                                                   89 89 90 90 90 90 90 90
+                                                   90 90 90 90 90 90 91 91
+                                                   91 91 91 91 91 91 91 91
+                                                   91 91 91 92 92 92 92 92
+                                                   92 92 92 92 92 92 92 92
+                                                   93 93 93 93 93 93 93 93
+                                                   93 93 93 93 93 93 94 94
+                                                   94 94 94 94 94 94 94 94
+                                                   94 94 94 94 95 95 95 95
+                                                   95 95 95 95 95 95 95 95
+                                                   95 96 96 96 96 96 96 96
+                                                   96 96 96 96 96 96 97 97
+                                                   97 97 97 97 97 97 97 97
+                                                   98 99 99 100 101 101 102 103
+                                                   103 104 105 105 106 107 107 108
+                                                   109 110 110 111 112 112 113 114
+                                                   114 115 115 116 117 117 118 119
+                                                   119 120 120 121 121 122 123 123
+                                                   124 124 125 125 126 126 127 128
+                                                   128 129 129 130 130 131 131 132
+                                                   132 133 133 134 134 135 135 136
+                                                   136 137 138 138 139 139 140 140
+                                                   141 141 142 142 143 143 144 144
+                                                   144 145 145 146 146 147 147 148
+                                                   148 149 149 150 150 151 151 152
+                                                   152 153 153 153 154 154 155 155
+                                                   156 156 157 157 157 158 158 159
+                                                   159 160 160 160 161 161 162 162
+                                                   162 163 163 164 164 164 165 165
+                                                   165 166 166 167 167 167 168 168
+                                                   168 169 169 169 170 170 171 171
+                                                   171 172 172 172 173 173 173 174
+                                                   174 174 175 175 175 176 176 176
+                                                   177 177 177 178 178 178 179 179
+                                                   179 180 180 180 181 181 181 182
+                                                   182 182 183 183 183 184 184 184
+                                                   185 185 185 185 186 186 186 187
+                                                   187 187 188 188 188 189 189 189
+                                                   190 190 190 191 191 191 191 192
+                                                   192 192 193 193 193 194 194 194
+                                                   195 195 195 195 196 196 196 197
+                                                   197 197 198 198 198 199 199 199
+                                                   199 200 200 200 201 201 201 202
+                                                   202 202 203 203 203 203 204 204
+                                                   204 205 205 205 206 206 206 207
+                                                   207 207 208 208 208 208 209 209
+                                                   209 210 210 210 211 211 211 212
+                                                   212 212 213 213 213 214 214 214
+                                                   215 215 215 215 216 216 216 217
+                                                   217 217 218 218 218 219 219 219
+                                                   220 220 220 220 221 221 221 222
+                                                   222 222 222 223 223 223 224 224
+                                                   224 224 225 225 225 226 226 226
+                                                   226 227 227 227 227 228 228 228
+                                                   229 229 229 229 230 230 230 230
+                                                   230 231 231 231 231 232 232 232
+                                                   232 233 233 233 233 234 234 234
+                                                   234 234 235 235 235 235 236 236
+                                                   236 236 236 237 237 237 237 238
+                                                   238 238 238 238 239 239 239 239
+                                                   239 240 240 240 240 240 241 241
+                                                   241 241 241 242 242 242 242 243
+                                                   243 243 243 243 244 244 244 244
+                                                   244 245 245 245 245 245 246 246
+                                                   246 246 246 247 247 247 247 248
+                                                   248 248 248 248 249 249 249 249
+                                                   250 250 250 250 251 251 251 251
+                                                   251 252 252 252 253 253 253 253
+                                                   254 254 254 254 255 255 255 255 >;
+                       };
+               };
+
+               /* tegradc.1 */
+               dc@54240000 {
+                       compatible = "nvidia,tegra114-dc";
+                       reg = <0x54240000 0x00040000>;
+                       interrupts = <0 74 0x04>;
+                       status = "okay";
+                       nvidia,dc_flags = "dc_flag_en";
+                       nvidia,emc_clk_rate = <300000000>;
+                       nvidia,cmu-enable = <1>;
+                       dc-default-out {
+                               nvidia,out-type = "hdmi";
+                               nvidia,out-flags = "hotplug_high";
+                               nvidia,out-parent-clk = "pll_d2_out0";
+                               nvidia,out-max-pixclk = <297000>;
+                               nvidia,out-align = "msb";
+                               nvidia,out-order = "rtob"; /*red to blue*/
+                               nvidia,out-hotplug-gpio = <&gpio 111 1>;
+                       };
+                       framebuffer-data {
+                               nvidia,fb-bpp = <32>; /* bits per pixel */
+                               nvidia,fb-flags = "flip_on_probe";
+                               nvidia,fb-xres = <1280>;
+                               nvidia,fb-yres = <720>;
+                       };
+               };
+       };
+
diff --git a/Documentation/devicetree/bindings/video/nvidia,tegra114-dsi.txt b/Documentation/devicetree/bindings/video/nvidia,tegra114-dsi.txt
new file mode 100644 (file)
index 0000000..34f7eec
--- /dev/null
@@ -0,0 +1,61 @@
+NVIDIA TEGRA114 Display Serial Interface
+========================================
+
+1) The dsi node:
+ dsi node must be contained in host1x parent node. This node represents NVIDIA Tegra114 Display
+ Serial Interface.
+
+ Required properties
+ - name: dsi
+ - compatible: Should contain "nvidia,tegra114-dsi".
+ - reg: Physical base address and length of the controller's registers.
+ - nvidia,panel: phandle for panel device data.
+ - nvidia,dsi-n-data-lanes: Number of DSI lanes in use. Should be one of 2, 3, 4, and 8
+ - nvidia,dsi-video-burst-mode: Video mode, Should be "none_burst_sync_end" or "none_burst" or
+   "burst_lowest_speed" or "burst_low_speed" or "burst_mid_speed" or "burst_fast_speed" or
+   "burst_fastest_speed".
+ - nvidia,dsi-pixel-format: DSI pixel data format. Should be "24_p" or "16_p" or "18_p" or "18_np".
+   p indicates packed.
+ - nvidia,dsi-ref-rate: Refresh rate.
+ - nvidia,dsi-virtual-ch: DSI virtual channel number. Should be "vc0" or  "vc1" or "vc2" or "vc3".
+ - nvidia,dsi-instance: Should be 0 or 1: DSI controller or DSIB controller.
+ - nvidia,dsi-panel-reset: Indicate if dsi output device requires hardware reset or not.
+ - nvidia,dsi-power-saving-suspend: With enabled, set dsi controller ultra low power mode in suspend.
+ - nvidia,dsi-video-data-type: The DSI operates in two transmission modes: video and host/command.
+   Should be "video" or "cmd".
+ - nvidia,dsi-video-clk-mode: Control for the hs clock lane. Continuous means hs clock on all the time.
+   Txonly means only hs clock active during hs transmissions. Should be "txonly" or "continuous".
+ - nvidia,dsi-phy-hsdexit : dsi phy timing, t_hsdexit_ns.
+ - nvidia,dsi-phy-hstrail : dsi phy timing, t_hstrail_ns.
+ - nvidia,dsi-phy-datzero : dsi phy timing, t_datzero_ns.
+ - nvidia,dsi-phy-hsprepare : dsi phy timing, t_hsprepare_ns.
+ - nvidia,dsi-phy-clktrail : dsi phy timing, t_clktrail_ns.
+ - nvidia,dsi-phy-clkpost : dsi phy timing, t_clkpost_ns.
+ - nvidia,dsi-phy-clkzero : dsi phy timing, t_clkzero_ns.
+ - nvidia,dsi-phy-tlpx : dsi phy timing, t_tlpx_ns.
+ - nvidia,dsi-phy-clkprepare : dsi phy timing, t_clkprepare_ns.
+ - nvidia,dsi-phy-clkpre : dsi phy timing, t_clkpre_ns.
+ - nvidia,dsi-phy-wakeup : dsi phy timing, t_wakeup_ns.
+ - nvidia,dsi-phy-taget : dsi phy timing, t_taget_ns.
+ - nvidia,dsi-phy-tasure : dsi phy timing, t_tasure_ns.
+ - nvidia,dsi-phy-tago : dsi phy timing, t_tago_ns.
+
+Example
+       host1x {
+               dsi {
+                       compatible = "nvidia,tegra114-dsi";
+                       reg = <0x54300000 0x00040000>;
+                       status = "okay";
+                       nvidia,panel = <&panel>;
+                       nvidia,dsi-n-data-lanes = <4>;
+                       nvidia,dsi-video-burst-mode = "none_burst_sync_end";
+                       nvidia,dsi-pixel-format = "24_p";
+                       nvidia,dsi-ref-rate = <60>;
+                       nvidia,dsi-virtual-ch = "vc0";
+                       nvidia,dsi-instance = <0>; /* 0 or 1 */
+                       nvidia,dsi-panel-reset = <1>;
+                       nvidia,dsi-power-saving-suspend = <1>;
+                       nvidia,dsi-video-data-type = "video";
+                       nvidia,dsi-video-clk-mode = "txonly";
+               };
+       };
diff --git a/Documentation/devicetree/bindings/video/nvidia,tegra114-hdmi.txt b/Documentation/devicetree/bindings/video/nvidia,tegra114-hdmi.txt
new file mode 100644 (file)
index 0000000..64f9794
--- /dev/null
@@ -0,0 +1,34 @@
+NVIDIA TEGRA114 High Definition Multimedia Interface
+====================================================
+
+1) The hdmi node:
+ hdmi node must be contained in host1x parent node. This node represents NVIDIA TEGRA114
+ High Definition Multimedia Interface.
+
+ Required properties
+ - name: hdmi
+ - compatible: Should contain "nvidia,tegra114-hdmi".
+ - reg: Physical base address and length of the controller's registers.
+ - interrupts: The interrupt outputs from the controller.
+ - nvidia,regulators: regulator names for supply voltage, PLL and hdmi 5V source should be
+   written in sequence.
+
+ Optional properties:
+ - nvidia,ddc-i2c-bus: phandle of an I2C controller used for DDC EDID probing
+ - nvidia,hpd-gpio: specifies a GPIO used for hotplug detection
+ - nvidia,edid: supplies a binary EDID blob
+
+Example
+       host1x {
+               hdmi {
+                       compatible = "nvidia,tegra114-hdmi";
+                       reg = <0x54280000 0x00040000>;
+                       interrupts = <0 75 0x04>;
+                       status = "okay";
+                       nvidia,regulators = "avdd_hdmi",
+                                           "avdd_hdmi_pll",
+                                           "vdd_hdmi_5v0";
+                       nvidia,ddc-i2c-bus = <&hdmi_ddc>;
+                       nvidia,hpd-gpio = <&gpio 111 1>;
+               };
+       };
index 0fb4ea5..c05bb46 100644 (file)
@@ -675,6 +675,16 @@ struct tegra_fb_data {
 
 #define TEGRA_FB_FLIP_ON_PROBE         (1 << 0)
 
+struct of_tegra_dc_data {
+       unsigned long           fb_size;
+       unsigned long           fb_start;
+       unsigned long           carveout_size;
+       unsigned long           carveout_start;
+       struct regulator        **of_regulators;
+       int                     *of_gpios;
+       int                     dc_controller;
+};
+
 struct tegra_dc_platform_data {
        unsigned long           flags;
        unsigned long           emc_clk_rate;
@@ -685,6 +695,7 @@ struct tegra_dc_platform_data {
        bool                    cmu_enable;
        struct tegra_dc_cmu     *cmu;
 #endif
+       struct of_tegra_dc_data of_data;
 };
 
 #define TEGRA_DC_FLAG_ENABLED          (1 << 0)
@@ -794,4 +805,29 @@ struct tegra_hdmi_out {
        struct tmds_config *tmds_config;
        int n_tmds_config;
 };
+
+struct of_tegra_lcd_devdata {
+       int     (*enable)(struct device *);
+       int     (*postpoweron)(struct device *);
+       int     (*prepoweroff)(void);
+       int     (*disable)(void);
+
+       int     (*hotplug_init)(struct device *);
+       int     (*postsuspend)(void);
+
+       struct tegra_dsi_cmd    *dsi_init_cmd;          /* required */
+       u16                     n_init_cmd;                     /* required */
+       struct tegra_dsi_cmd    *dsi_early_suspend_cmd;
+       u16                     n_early_suspend_cmd;
+       struct tegra_dsi_cmd    *dsi_late_resume_cmd;
+       u16                     n_late_resume_cmd;
+       struct tegra_dsi_cmd    *dsi_suspend_cmd;       /* required */
+       u16                     n_suspend_cmd;                  /* required */
+       const u32               *pkt_seq;
+};
+
+void lcd_devdata_to_dc_set_callback(struct device*(*func)
+       (struct device_node *));
+struct device *lcd_devdata_to_dc_callback_run(struct device_node *dn);
+
 #endif
index 0aa3119..06e2ba8 100644 (file)
@@ -2,6 +2,7 @@ GCOV_PROFILE := y
 EXTRA_CFLAGS += -Idrivers/video/tegra/host
 obj-y += dc.o bandwidth.o mode.o clock.o lut.o csc.o window.o
 obj-y += rgb.o
+obj-y += of_dc.o
 obj-y += hdmi.o
 obj-y += dsi2lvds.o
 obj-y += tc358770_dsi2edp.o
index de54cdf..a7dcb83 100644 (file)
@@ -40,6 +40,8 @@
 #ifdef CONFIG_SWITCH
 #include <linux/switch.h>
 #endif
+#include <linux/of_irq.h>
+#include <linux/of_address.h>
 
 #define CREATE_TRACE_POINTS
 #include <trace/events/display.h>
@@ -2257,9 +2259,14 @@ static int tegra_dc_probe(struct platform_device *ndev)
 {
        struct tegra_dc *dc;
        struct tegra_dc_mode *mode;
+       struct tegra_dc_platform_data *dt_pdata = NULL;
+       struct tegra_dc_platform_data *temp_pdata;
+       struct of_tegra_dc_data *of_pdata = NULL;
        struct clk *clk;
+       struct device_node *np = ndev->dev.of_node;
        struct clk *emc_clk;
-       struct resource *res;
+       struct resource *res;
+       struct resource dt_res;
        struct resource *base_res;
        struct resource *fb_mem = NULL;
        int ret = 0;
@@ -2278,18 +2285,44 @@ static int tegra_dc_probe(struct platform_device *ndev)
                return -ENOMEM;
        }
 
-       irq = platform_get_irq_byname(ndev, "irq");
-       if (irq <= 0) {
-               dev_err(&ndev->dev, "no irq\n");
-               ret = -ENOENT;
-               goto err_free;
-       }
+       if (np) {
+               dt_pdata = of_dc_parse_platform_data(ndev);
+               if (dt_pdata == NULL)
+                       goto err_free;
 
-       res = platform_get_resource_byname(ndev, IORESOURCE_MEM, "regs");
-       if (!res) {
-               dev_err(&ndev->dev, "no mem resource\n");
-               ret = -ENOENT;
-               goto err_free;
+#ifdef CONFIG_OF
+               irq = of_irq_to_resource(np, 0, NULL);
+               if (!irq)
+                       goto err_free;
+#endif
+
+               ret = of_address_to_resource(np, 0, &dt_res);
+               if (ret)
+                       goto err_free;
+
+               if (dt_res.start == TEGRA_DISPLAY_BASE)
+                       ndev->id = 0;
+               else if (dt_res.start == TEGRA_DISPLAY2_BASE)
+                       ndev->id = 1;
+               else
+                       goto err_free;
+
+               res = &dt_res;
+       } else {
+               irq = platform_get_irq_byname(ndev, "irq");
+               if (irq <= 0) {
+                       dev_err(&ndev->dev, "no irq\n");
+                       ret = -ENOENT;
+                       goto err_free;
+               }
+
+               res = platform_get_resource_byname(ndev,
+                       IORESOURCE_MEM, "regs");
+               if (!res) {
+                       dev_err(&ndev->dev, "no mem resource\n");
+                       ret = -ENOENT;
+                       goto err_free;
+               }
        }
 
        base_res = request_mem_region(res->start, resource_size(res),
@@ -2329,8 +2362,24 @@ static int tegra_dc_probe(struct platform_device *ndev)
                        res->start);
        }
 
-
-       fb_mem = platform_get_resource_byname(ndev, IORESOURCE_MEM, "fbmem");
+       if (np) {
+               temp_pdata = (struct tegra_dc_platform_data *)
+                       ndev->dev.platform_data;
+               of_pdata = &(temp_pdata->of_data);
+               fb_mem = kzalloc(sizeof(struct resource), GFP_KERNEL);
+               if (fb_mem == NULL) {
+                       ret = -ENOMEM;
+                       goto err_iounmap_reg;
+               }
+               fb_mem->name = "fbmem";
+               fb_mem->flags = IORESOURCE_MEM;
+               fb_mem->start = (resource_size_t) of_pdata->fb_start;
+               fb_mem->end = fb_mem->start +
+                       (resource_size_t)of_pdata->fb_size - 1;
+       } else {
+               fb_mem = platform_get_resource_byname(ndev,
+                       IORESOURCE_MEM, "fbmem");
+       }
 
        clk = clk_get(&ndev->dev, NULL);
        if (IS_ERR_OR_NULL(clk)) {
@@ -2357,7 +2406,11 @@ static int tegra_dc_probe(struct platform_device *ndev)
        dc->base = base;
        dc->irq = irq;
        dc->ndev = ndev;
-       dc->pdata = ndev->dev.platform_data;
+
+       if (!np)
+               dc->pdata = ndev->dev.platform_data;
+       else
+               dc->pdata = dt_pdata;
 
        /*
         * The emc is a shared clock, it will be set based on
@@ -2511,8 +2564,12 @@ err_put_clk:
        clk_put(clk);
 err_iounmap_reg:
        iounmap(base);
-       if (fb_mem)
-               release_resource(fb_mem);
+       if (fb_mem) {
+               if (!np)
+                       release_resource(fb_mem);
+               else
+                       kfree(fb_mem);
+       }
 err_release_resource_reg:
        release_resource(base_res);
 err_free:
@@ -2524,14 +2581,19 @@ err_free:
 static int __devexit tegra_dc_remove(struct platform_device *ndev)
 {
        struct tegra_dc *dc = platform_get_drvdata(ndev);
+       struct device_node *np = ndev->dev.of_node;
 
        tegra_dc_remove_sysfs(&dc->ndev->dev);
        tegra_dc_remove_debugfs(dc);
 
        if (dc->fb) {
                tegra_fb_unregister(dc->fb);
-               if (dc->fb_mem)
-                       release_resource(dc->fb_mem);
+               if (dc->fb_mem) {
+                       if (!np)
+                               release_resource(dc->fb_mem);
+                       else
+                               kfree(dc->fb_mem);
+               }
        }
 
        tegra_dc_ext_disable(dc->ext);
@@ -2654,10 +2716,21 @@ int suspend;
 
 module_param_call(suspend, suspend_set, suspend_get, &suspend, 0644);
 
+
+#ifdef CONFIG_OF
+static struct of_device_id tegra_display_of_match[] __devinitdata = {
+       {.compatible = "nvidia,tegra114-dc", },
+       { },
+};
+#endif
+
 struct platform_driver tegra_dc_driver = {
        .driver = {
                .name = "tegradc",
                .owner = THIS_MODULE,
+#ifdef CONFIG_OF
+               .of_match_table = tegra_display_of_match,
+#endif
        },
        .probe = tegra_dc_probe,
        .remove = tegra_dc_remove,
index a341b43..0b55408 100644 (file)
@@ -338,4 +338,7 @@ void tegra_dc_cmu_enable(struct tegra_dc *dc, bool cmu_enable);
 int tegra_dc_update_cmu(struct tegra_dc *dc, struct tegra_dc_cmu *cmu);
 #endif
 
+struct tegra_dc_platform_data
+       *of_dc_parse_platform_data(struct platform_device *ndev);
+
 #endif
index 59f427c..cb16784 100644 (file)
@@ -38,6 +38,7 @@
 #include <mach/csi.h>
 #include <mach/iomap.h>
 #include <linux/nvhost.h>
+#include <linux/of_address.h>
 
 #include "dc_reg.h"
 #include "dc_priv.h"
@@ -3888,6 +3889,7 @@ static int _tegra_dc_dsi_init(struct tegra_dc *dc)
        struct tegra_dc_dsi_data *dsi;
        struct resource *res;
        struct resource *base_res;
+       struct resource dsi_res;
        void __iomem *base;
        struct clk *dc_clk = NULL;
        struct clk *dsi_clk = NULL;
@@ -3897,6 +3899,9 @@ static int _tegra_dc_dsi_init(struct tegra_dc *dc)
        char *ganged_reg_name[2] = {"ganged_dsia_regs", "ganged_dsib_regs"};
        char *dsi_clk_name[2] = {"dsia", "dsib"};
        char *dsi_lp_clk_name[2] = {"dsialp", "dsiblp"};
+       struct device_node *np = dc->ndev->dev.of_node;
+       struct device_node *np_dsi =
+               of_find_compatible_node(NULL, NULL, "nvidia,tegra114-dsi");
 
        dsi = kzalloc(sizeof(*dsi), GFP_KERNEL);
        if (!dsi) {
@@ -3911,10 +3916,17 @@ static int _tegra_dc_dsi_init(struct tegra_dc *dc)
 
        dsi->max_instances = dc->out->dsi->ganged_type ? MAX_DSI_INSTANCE : 1;
        for (i = 0; i < dsi->max_instances; i++) {
-               res = platform_get_resource_byname(dc->ndev,
-                                       IORESOURCE_MEM,
-                                       dc->out->dsi->ganged_type ?
-                                       ganged_reg_name[i] : "dsi_regs");
+               if (np && np_dsi) {
+                       of_address_to_resource(np_dsi, i, &dsi_res);
+                       res = &dsi_res;
+               } else {
+                       res = platform_get_resource_byname(dc->ndev,
+                                               IORESOURCE_MEM,
+                                               dc->out->dsi->ganged_type ?
+                                               ganged_reg_name[i] :
+                                               "dsi_regs");
+               }
+
                if (!res) {
                        dev_err(&dc->ndev->dev, "dsi: no mem resource\n");
                        err = -ENOENT;
index 1cc6c01..60cb079 100644 (file)
@@ -49,6 +49,8 @@
 #include "hdmi.h"
 #include "edid.h"
 #include "nvhdcp.h"
+#include <linux/of.h>
+#include <linux/of_address.h>
 
 /* datasheet claims this will always be 216MHz */
 #define HDMI_AUDIOCLK_FREQ             216000000
@@ -1061,6 +1063,7 @@ static int tegra_dc_hdmi_init(struct tegra_dc *dc)
 {
        struct tegra_dc_hdmi_data *hdmi;
        struct resource *res;
+       struct resource hdmi_res;
        struct resource *base_res;
 #ifdef CONFIG_SWITCH
        int ret;
@@ -1071,13 +1074,20 @@ static int tegra_dc_hdmi_init(struct tegra_dc *dc)
        struct clk *disp2_clk = NULL;
        struct tegra_hdmi_out *hdmi_out = NULL;
        int err;
+       struct device_node *np = dc->ndev->dev.of_node;
+       struct device_node *np_hdmi =
+               of_find_compatible_node(NULL, NULL, "nvidia,tegra114-hdmi");
 
        hdmi = kzalloc(sizeof(*hdmi), GFP_KERNEL);
        if (!hdmi)
                return -ENOMEM;
-
-       res = platform_get_resource_byname(dc->ndev,
-               IORESOURCE_MEM, "hdmi_regs");
+       if (np && np_hdmi) {
+               of_address_to_resource(np_hdmi, 0, &hdmi_res);
+               res = &hdmi_res;
+       } else {
+               res = platform_get_resource_byname(dc->ndev,
+                       IORESOURCE_MEM, "hdmi_regs");
+       }
        if (!res) {
                dev_err(&dc->ndev->dev, "hdmi: no mem resource\n");
                err = -ENOENT;
index 6d8e33d..c8340ca 100644 (file)
@@ -20,6 +20,7 @@
 #include "mipi_cal.h"
 #include "mipi_cal_regs.h"
 #include "dsi.h"
+#include <linux/of_address.h>
 
 int tegra_mipi_cal_init_hw(struct tegra_mipi_cal *mipi_cal)
 {
@@ -63,10 +64,16 @@ struct tegra_mipi_cal *tegra_mipi_cal_init_sw(struct tegra_dc *dc)
 {
        struct tegra_mipi_cal *mipi_cal;
        struct resource *res;
+       struct resource mipi_res;
+       struct resource *base_res;
        struct clk *clk;
        struct clk *fixed_clk;
        void __iomem *base;
        int err = 0;
+       struct device_node *np = dc->ndev->dev.of_node;
+       struct device_node *np_mipi_cal =
+               of_find_compatible_node(NULL,
+                       NULL, "nvidia,tegra114-mipical");
 
        mipi_cal = devm_kzalloc(&dc->ndev->dev, sizeof(*mipi_cal), GFP_KERNEL);
        if (!mipi_cal) {
@@ -75,15 +82,22 @@ struct tegra_mipi_cal *tegra_mipi_cal_init_sw(struct tegra_dc *dc)
                goto fail;
        }
 
-       res = platform_get_resource_byname(dc->ndev,
+       if (np && np_mipi_cal) {
+               of_address_to_resource(np_mipi_cal, 0, &mipi_res);
+               res = &mipi_res;
+       } else {
+               res = platform_get_resource_byname(dc->ndev,
                                IORESOURCE_MEM, "mipi_cal");
+       }
        if (!res) {
                dev_err(&dc->ndev->dev, "mipi_cal: no entry in resource\n");
                err = -ENOENT;
                goto fail_free_mipi_cal;
        }
 
-       base = devm_request_and_ioremap(&dc->ndev->dev, res);
+       base_res = request_mem_region(res->start,
+               resource_size(res), dc->ndev->name);
+       base = ioremap(res->start, resource_size(res));
        if (!base) {
                dev_err(&dc->ndev->dev, "mipi_cal: bus to virtual mapping failed\n");
                err = -EBUSY;
@@ -113,8 +127,8 @@ struct tegra_mipi_cal *tegra_mipi_cal_init_sw(struct tegra_dc *dc)
        return mipi_cal;
 
 fail_free_map:
-       devm_iounmap(&dc->ndev->dev, base);
-       devm_release_mem_region(&dc->ndev->dev, res->start, resource_size(res));
+       iounmap(base);
+       release_resource(base_res);
 fail_free_res:
        release_resource(res);
 fail_free_mipi_cal:
@@ -135,9 +149,9 @@ void tegra_mipi_cal_destroy(struct tegra_dc *dc)
        mutex_lock(&mipi_cal->lock);
 
        clk_put(mipi_cal->clk);
-       devm_iounmap(&dc->ndev->dev, mipi_cal->base);
-       devm_release_mem_region(&dc->ndev->dev, mipi_cal->res->start,
-                                       resource_size(mipi_cal->res));
+       iounmap(mipi_cal->base);
+       release_resource(mipi_cal->base_res);
+
        release_resource(mipi_cal->res);
 
        mutex_unlock(&mipi_cal->lock);
index 47b764c..0aff6e3 100644 (file)
@@ -22,6 +22,7 @@
 struct tegra_mipi_cal {
        struct tegra_dc *dc;
        struct resource *res;
+       struct resource *base_res;
        struct clk *clk;
        struct clk *fixed_clk;
        void __iomem *base;
diff --git a/drivers/video/tegra/dc/of_dc.c b/drivers/video/tegra/dc/of_dc.c
new file mode 100644 (file)
index 0000000..7d35b9d
--- /dev/null
@@ -0,0 +1,1296 @@
+/*
+ * drivers/video/tegra/dc/of_dc.c
+ *
+ * Copyright (c) 2013, NVIDIA CORPORATION.  All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/err.h>
+#include <linux/errno.h>
+#include <linux/interrupt.h>
+#include <linux/slab.h>
+#include <linux/io.h>
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/workqueue.h>
+#include <linux/ktime.h>
+#include <linux/debugfs.h>
+#include <linux/seq_file.h>
+#include <linux/gpio.h>
+#include <linux/i2c.h>
+#include <linux/regulator/consumer.h>
+#include <linux/of_platform.h>
+#include <linux/of.h>
+#include <linux/of_irq.h>
+#include <linux/of_address.h>
+#include <linux/of_gpio.h>
+#include <linux/of_i2c.h>
+#include <linux/nvhost.h>
+#include <linux/timer.h>
+
+#include <mach/clk.h>
+#include <mach/dc.h>
+#include <mach/fb.h>
+#include <mach/mc.h>
+#include <mach/latency_allowance.h>
+#include <mach/iomap.h>
+
+#include "dc_reg.h"
+#include "dc_config.h"
+#include "dc_priv.h"
+#include "dev.h"
+#include "nvsd.h"
+
+#ifdef CONFIG_OF
+/* #define OF_DC_DEBUG 1 */
+
+#undef OF_DC_LOG
+#ifdef OF_DC_DEBUG
+#define OF_DC_LOG(fmt, args...) pr_info("OF_DC_LOG: " fmt, ## args)
+#else
+#define OF_DC_LOG(fmt, args...)
+#endif
+
+#define HDMI_REGULATORS_COUNT          2
+#define HDMI_5V0_REG_COUNT             1
+#define HDMI_REGS_TOTAL                        \
+       (HDMI_REGULATORS_COUNT + HDMI_5V0_REG_COUNT)
+
+enum {
+       DC_CONTROLLER_0 = 1,
+       DC_CONTROLLER_1,
+};
+
+static atomic_t sd_brightness = ATOMIC_INIT(255);
+
+static struct regulator *of_regulators_dc1[HDMI_REGS_TOTAL];
+
+#define TYPICAL_SEARCH_ITER    3
+
+static const char *typical_sd_settings[TYPICAL_SEARCH_ITER] = {
+       "nvidia,aggressiveness",
+       "nvidia,lut",
+       "nvidia,bl-device-name",
+};
+
+static const char *typical_dsi_out[TYPICAL_SEARCH_ITER] = {
+       "nvidia,dsi-n-data-lanes",
+       "nvidia,dsi-video-burst-mode",
+       "nvidia,dsi-pixel-format",
+};
+
+#ifdef CONFIG_TEGRA_DC_CMU
+static const char *typical_cmu[TYPICAL_SEARCH_ITER] = {
+       "nvidia,cmu-csc",
+       "nvidia,cmu-lut2",
+       "nvidia,cmu-lut2", /* dummy to have TYPICAL_SEARCH_ITER components */
+};
+
+static struct tegra_dc_cmu default_cmu = {
+       /* lut1 maps sRGB to linear space. */
+       {
+               0,    1,    2,    4,    5,    6,    7,    9,
+               10,   11,   12,   14,   15,   16,   18,   20,
+               21,   23,   25,   27,   29,   31,   33,   35,
+               37,   40,   42,   45,   48,   50,   53,   56,
+               59,   62,   66,   69,   72,   76,   79,   83,
+               87,   91,   95,   99,   103,  107,  112,  116,
+               121,  126,  131,  136,  141,  146,  151,  156,
+               162,  168,  173,  179,  185,  191,  197,  204,
+               210,  216,  223,  230,  237,  244,  251,  258,
+               265,  273,  280,  288,  296,  304,  312,  320,
+               329,  337,  346,  354,  363,  372,  381,  390,
+               400,  409,  419,  428,  438,  448,  458,  469,
+               479,  490,  500,  511,  522,  533,  544,  555,
+               567,  578,  590,  602,  614,  626,  639,  651,
+               664,  676,  689,  702,  715,  728,  742,  755,
+               769,  783,  797,  811,  825,  840,  854,  869,
+               884,  899,  914,  929,  945,  960,  976,  992,
+               1008, 1024, 1041, 1057, 1074, 1091, 1108, 1125,
+               1142, 1159, 1177, 1195, 1213, 1231, 1249, 1267,
+               1286, 1304, 1323, 1342, 1361, 1381, 1400, 1420,
+               1440, 1459, 1480, 1500, 1520, 1541, 1562, 1582,
+               1603, 1625, 1646, 1668, 1689, 1711, 1733, 1755,
+               1778, 1800, 1823, 1846, 1869, 1892, 1916, 1939,
+               1963, 1987, 2011, 2035, 2059, 2084, 2109, 2133,
+               2159, 2184, 2209, 2235, 2260, 2286, 2312, 2339,
+               2365, 2392, 2419, 2446, 2473, 2500, 2527, 2555,
+               2583, 2611, 2639, 2668, 2696, 2725, 2754, 2783,
+               2812, 2841, 2871, 2901, 2931, 2961, 2991, 3022,
+               3052, 3083, 3114, 3146, 3177, 3209, 3240, 3272,
+               3304, 3337, 3369, 3402, 3435, 3468, 3501, 3535,
+               3568, 3602, 3636, 3670, 3705, 3739, 3774, 3809,
+               3844, 3879, 3915, 3950, 3986, 4022, 4059, 4095,
+       },
+       /* csc */
+       {
+               0,
+       },
+       /*lut2*/
+       {
+               0,
+       }
+};
+#endif
+#endif
+
+typedef struct device *(*tegra_lcd_devdata_to_dc_CB)(struct device_node *);
+tegra_lcd_devdata_to_dc_CB tegra_lcd_devdata_to_dc;
+
+void lcd_devdata_to_dc_set_callback(struct device*(*func)
+       (struct device_node *))
+{
+       if (func != NULL)
+               tegra_lcd_devdata_to_dc = func;
+}
+EXPORT_SYMBOL(lcd_devdata_to_dc_set_callback);
+
+struct device *lcd_devdata_to_dc_callback_run(struct device_node *dn)
+{
+       struct device *rdev = NULL;
+
+       if (tegra_lcd_devdata_to_dc)
+               rdev = tegra_lcd_devdata_to_dc(dn);
+
+       return rdev;
+}
+EXPORT_SYMBOL(lcd_devdata_to_dc_callback_run);
+
+#ifdef CONFIG_OF
+static int parse_dc_out_type(struct device_node *np,
+               struct tegra_dc_out *default_out)
+{
+       const char *temp_str0;
+       if (!of_property_read_string(np, "nvidia,out-type", &temp_str0)) {
+               if (!strncmp(temp_str0, "dsi", strlen(temp_str0))) {
+                       default_out->type = TEGRA_DC_OUT_DSI;
+                       OF_DC_LOG("dsi out\n");
+               } else if (!strncmp(temp_str0, "hdmi", strlen(temp_str0))) {
+                       default_out->type = TEGRA_DC_OUT_HDMI;
+                       OF_DC_LOG("hdmi out\n");
+               } else {
+                       pr_err("no dc out support except dsi / hdmi\n");
+                       return -EINVAL;
+               }
+       }
+       return 0;
+}
+
+static int parse_dc_default_out(struct device_node *np,
+               struct tegra_dc_out *default_out)
+{
+       int err;
+       u32 temp;
+       const char *temp_str0;
+       int hotplug_gpio = 0;
+       enum of_gpio_flags flags;
+       struct i2c_client *i2c;
+       struct device_node *ddc;
+       struct device_node *np_hdmi =
+               of_find_compatible_node(NULL, NULL, "nvidia,tegra114-hdmi");
+       struct i2c_adapter *adapter;
+
+       err = parse_dc_out_type(np, default_out);
+       if (err) {
+               pr_err("parse_dc_out_type err\n");
+               return err;
+       }
+       if (!of_property_read_u32(np, "nvidia,out-width", &temp)) {
+               default_out->width = (unsigned) temp;
+               OF_DC_LOG("out_width %d\n", default_out->width);
+       }
+       if (!of_property_read_u32(np, "nvidia,out-height", &temp)) {
+               default_out->height = (unsigned) temp;
+               OF_DC_LOG("out_height %d\n", default_out->height);
+       }
+       if (np_hdmi && (default_out->type == TEGRA_DC_OUT_HDMI)) {
+               ddc = of_parse_phandle(np_hdmi, "nvidia,ddc-i2c-bus", 0);
+               i2c = of_find_i2c_device_by_node(ddc);
+               adapter = to_i2c_adapter(&(i2c->dev));
+               default_out->dcc_bus = adapter->nr;
+               OF_DC_LOG("out_dcc bus %d\n", (int)adapter->nr);
+
+               hotplug_gpio = of_get_named_gpio_flags(np_hdmi,
+                               "nvidia,hpd-gpio", 0, &flags);
+               if (hotplug_gpio != 0)
+                       default_out->hotplug_gpio = hotplug_gpio;
+       }
+       if (!of_property_read_u32(np, "nvidia,out-max-pixclk", &temp)) {
+               default_out->max_pixclock = (unsigned) KHZ2PICOS(temp);
+               OF_DC_LOG("khz %d => out_dcc %d in picos unit\n",
+                       temp, default_out->max_pixclock);
+       }
+       if (!of_property_read_string(np, "nvidia,out-flags", &temp_str0)) {
+               if (!strncmp(temp_str0, "continuous", strlen(temp_str0))) {
+                       default_out->flags = TEGRA_DC_OUT_CONTINUOUS_MODE;
+               } else if (!strncmp(temp_str0, "oneshot", strlen(temp_str0))) {
+                       default_out->flags = TEGRA_DC_OUT_ONE_SHOT_MODE;
+               } else if (!strncmp(temp_str0, "continuous_initialized",
+                       strlen(temp_str0))) {
+                       default_out->flags = TEGRA_DC_OUT_CONTINUOUS_MODE |
+                               TEGRA_DC_OUT_INITIALIZED_MODE;
+               } else if (!strncmp(temp_str0, "oneshot_initialized",
+                       strlen(temp_str0))) {
+                       default_out->flags = TEGRA_DC_OUT_ONE_SHOT_MODE |
+                               TEGRA_DC_OUT_INITIALIZED_MODE;
+               } else if (!strncmp(temp_str0,
+                       "hotplug_high", strlen(temp_str0))) {
+                       default_out->flags = TEGRA_DC_OUT_HOTPLUG_HIGH;
+               } else if (!strncmp(temp_str0,
+                       "hotplug_low", strlen(temp_str0))) {
+                       default_out->flags = TEGRA_DC_OUT_HOTPLUG_LOW;
+               } else {
+                       pr_err("invalid out flags\n");
+                       return -EINVAL;
+               }
+       }
+       if (!of_property_read_string(np, "nvidia,out-align", &temp_str0)) {
+               if (!strncmp(temp_str0, "msb", strlen(temp_str0))) {
+                       default_out->align = TEGRA_DC_ALIGN_MSB;
+               } else if (!strncmp(temp_str0, "lsb", strlen(temp_str0))) {
+                       default_out->align = TEGRA_DC_ALIGN_LSB;
+               } else {
+                       pr_err("invalid out align\n");
+                       return -EINVAL;
+               }
+       }
+       if (!of_property_read_string(np, "nvidia,out-order", &temp_str0)) {
+               if (!strncmp(temp_str0, "rtob", strlen(temp_str0))) {
+                       default_out->order = TEGRA_DC_ORDER_RED_BLUE;
+               } else if (!strncmp(temp_str0, "btor", strlen(temp_str0))) {
+                       default_out->order = TEGRA_DC_ORDER_BLUE_RED;
+               } else {
+                       pr_err("invalid out order\n");
+                       return -EINVAL;
+               }
+       }
+
+       if (!of_property_read_string(np, "nvidia,out-parent-clk", &temp_str0)) {
+               default_out->parent_clk = temp_str0;
+               OF_DC_LOG("parent clk %s\n",
+                       default_out->parent_clk);
+       } else {
+               goto fail_dc_default_out;
+       }
+       return 0;
+
+fail_dc_default_out:
+       pr_err("%s: a parse error\n", __func__);
+       return -EINVAL;
+}
+
+static int parse_sd_settings(struct device_node *np,
+       struct tegra_dc_sd_settings *sd_settings)
+{
+       struct property *prop;
+       const __be32 *p;
+       u32 u;
+       const char *sd_str1;
+       const char *sd_str2;
+       u8 coeff[3] = {0, };
+       u8 fc[2] = {0, };
+       u32 blp[2] = {0, };
+
+       int coeff_count = 0;
+       int fc_count = 0;
+       int blp_count = 0;
+       int bltf_count = 0;
+       u8 *addr;
+       int sd_lut[108] = {0, };
+       int sd_i = 0;
+       int  sd_j = 0;
+       int sd_index = 0;
+       u32 temp;
+       int err;
+
+       if (of_device_is_available(np))
+               sd_settings->enable = (unsigned) 1;
+       else
+               sd_settings->enable = (unsigned) 0;
+
+       OF_DC_LOG("nvidia,sd-enable %d\n", sd_settings->enable);
+
+       if (!of_property_read_u32(np, "nvidia,use-auto-pwm", &temp)) {
+               sd_settings->use_auto_pwm = (bool) temp;
+               OF_DC_LOG("nvidia,use-auto-pwm %d\n", temp);
+       }
+       if (!of_property_read_u32(np, "nvidia,hw-update-delay", &temp)) {
+               sd_settings->hw_update_delay = (u8) temp;
+               OF_DC_LOG("nvidia,hw-update-delay %d\n", temp);
+       }
+       if (!of_property_read_string(np, "nvidia,bin-width", &sd_str1)) {
+               int val;
+               err = kstrtoint(sd_str1, 10, &val);
+               if (err) {
+                       pr_err("invalid string for nvidia,bin-width\n");
+                       return err;
+               } else {
+                       sd_settings->bin_width = (short)val;
+                       OF_DC_LOG("nvidia,bin-width %d\n", val);
+               }
+       }
+       if (!of_property_read_u32(np, "nvidia,aggressiveness", &temp)) {
+               sd_settings->aggressiveness = (u8) temp;
+               OF_DC_LOG("nvidia,aggressiveness %d\n", temp);
+       }
+       if (!of_property_read_u32(np, "nvidia,use-vid-luma", &temp)) {
+               sd_settings->use_vid_luma = (bool) temp;
+               OF_DC_LOG("nvidia,use-vid-luma %d\n", temp);
+       }
+       if (!of_property_read_u32(np, "nvidia,phase-in-settings", &temp)) {
+               sd_settings->phase_in_settings = (u8) temp;
+               OF_DC_LOG("nvidia,phase-in-settings  %d\n", temp);
+       }
+       if (!of_property_read_u32(np,
+               "nvidia,phase-in-adjustments", &temp)) {
+               sd_settings->phase_in_adjustments = (u8) temp;
+               OF_DC_LOG("nvidia,phase-in-adjustments  %d\n", temp);
+       }
+       if (!of_property_read_u32(np, "nvidia,k-limit-enable", &temp)) {
+               sd_settings->k_limit_enable = (bool) temp;
+               OF_DC_LOG("nvidia,k-limit-enable  %d\n", temp);
+       }
+       if (!of_property_read_u32(np, "nvidia,k-limit", &temp)) {
+               sd_settings->k_limit = (u16) temp;
+               OF_DC_LOG("nvidia,k-limit  %d\n", temp);
+       }
+       if (!of_property_read_u32(np, "nvidia,sd-window-enable", &temp)) {
+               sd_settings->sd_window_enable = (bool) temp;
+               OF_DC_LOG("nvidia,sd-window-enable  %d\n", temp);
+       }
+       if (!of_property_read_u32(np,
+               "nvidia,soft-clipping-enable", &temp)) {
+               sd_settings->soft_clipping_enable = (bool) temp;
+               OF_DC_LOG("nvidia,soft-clipping-enable %d\n", temp);
+       }
+       if (!of_property_read_u32(np,
+               "nvidia,soft-clipping-threshold", &temp)) {
+               sd_settings->soft_clipping_threshold = (u8) temp;
+               OF_DC_LOG("nvidia,soft-clipping-threshold %d\n", temp);
+       }
+       if (!of_property_read_u32(np, "nvidia,smooth-k-enable", &temp)) {
+               sd_settings->smooth_k_enable = (bool) temp;
+               OF_DC_LOG("nvidia,smooth-k-enable %d\n", temp);
+       }
+       if (!of_property_read_u32(np, "nvidia,smooth-k-incr", &temp)) {
+               sd_settings->smooth_k_incr = (u16) temp;
+               OF_DC_LOG("nvidia,smooth-k-incr %d\n", temp);
+       }
+
+       sd_settings->sd_brightness = &sd_brightness;
+
+       if (!of_property_read_u32(np, "nvidia,use-vpulse2", &temp)) {
+               sd_settings->use_vpulse2 = (bool) temp;
+               OF_DC_LOG("nvidia,use-vpulse2 %d\n", temp);
+       }
+
+       if (!of_property_read_string(np, "nvidia,bl-device-name",
+               &sd_str2)) {
+               sd_settings->bl_device_name = (char *)sd_str2;
+               OF_DC_LOG("nvidia,bl-device-name %s\n", sd_str2);
+       }
+
+       coeff_count = 0;
+       of_property_for_each_u32(np, "nvidia,coeff", prop, p, u)
+               coeff_count++;
+
+       if (coeff_count > (sizeof(coeff) / sizeof(coeff[0]))) {
+               pr_err("sd_coeff overflow\n");
+               return -EINVAL;
+       } else {
+               coeff_count = 0;
+               of_property_for_each_u32(np, "nvidia,coeff", prop, p, u)
+                       coeff[coeff_count++] = (u8)u;
+               sd_settings->coeff.r = coeff[0];
+               sd_settings->coeff.g = coeff[1];
+               sd_settings->coeff.b = coeff[2];
+               OF_DC_LOG("nvidia,coeff %d %d %d\n",
+                               coeff[0], coeff[1], coeff[2]);
+       }
+       fc_count = 0;
+       of_property_for_each_u32(np, "nvidia,fc", prop, p, u)
+               fc_count++;
+
+       if (fc_count > sizeof(fc) / sizeof(fc[0])) {
+               pr_err("sd fc overflow\n");
+               return -EINVAL;
+       } else {
+               fc_count = 0;
+               of_property_for_each_u32(np, "nvidia,fc", prop, p, u)
+               fc[fc_count++] = (u8)u;
+
+               sd_settings->fc.time_limit = fc[0];
+               sd_settings->fc.threshold = fc[1];
+               OF_DC_LOG("nvidia,fc %d %d\n", fc[0], fc[1]);
+       }
+
+       blp_count = 0;
+       of_property_for_each_u32(np, "nvidia,blp", prop, p, u)
+               blp_count++;
+
+       if (blp_count > sizeof(blp) / sizeof(blp[0])) {
+               pr_err("sd blp overflow\n");
+               return -EINVAL;
+       } else {
+               blp_count = 0;
+               of_property_for_each_u32(np, "nvidia,blp", prop, p, u)
+                       blp[blp_count++] = (u32)u;
+               sd_settings->blp.time_constant = (u16)blp[0];
+               sd_settings->blp.step = (u8)blp[1];
+               OF_DC_LOG("nvidia,blp %d %d\n", blp[0], blp[1]);
+       }
+
+       bltf_count = 0;
+       of_property_for_each_u32(np, "nvidia,bltf", prop, p, u)
+               bltf_count++;
+
+       if (bltf_count > (sizeof(sd_settings->bltf) /
+                       sizeof(sd_settings->bltf[0][0][0]))) {
+               pr_err("sd bltf overflow of sd_settings\n");
+               return -EINVAL;
+       } else {
+               addr = &(sd_settings->bltf[0][0][0]);
+               of_property_for_each_u32(np, "nvidia,bltf", prop, p, u)
+                       *(addr++) = u;
+       }
+
+       sd_index = 0;
+       of_property_for_each_u32(np, "nvidia,lut", prop, p, u)
+               sd_index++;
+
+       if (sd_index > sizeof(sd_lut)/sizeof(sd_lut[0])) {
+               pr_err("sd lut size overflow of sd_settings\n");
+               return -EINVAL;
+       } else {
+               sd_index = 0;
+               of_property_for_each_u32(np, "nvidia,lut", prop, p, u)
+                       sd_lut[sd_index++] = u;
+
+               sd_index = 0;
+
+               if (prop) {
+                       for (sd_i = 0; sd_i < 4; sd_i++)
+                               for (sd_j = 0; sd_j < 9; sd_j++) {
+                                       sd_settings->lut[sd_i][sd_j].r =
+                                               sd_lut[sd_index++];
+                                       sd_settings->lut[sd_i][sd_j].g =
+                                               sd_lut[sd_index++];
+                                       sd_settings->lut[sd_i][sd_j].b =
+                                               sd_lut[sd_index++];
+                       }
+               }
+       }
+       return 0;
+}
+
+static int parse_modes(struct device_node *np,
+       struct tegra_dc_mode *modes)
+{
+       u32 temp;
+
+       if (!of_property_read_u32(np, "clock-frequency", &temp)) {
+               modes->pclk = temp;
+               OF_DC_LOG("of pclk %d\n", temp);
+       } else {
+               goto parse_modes_fail;
+       }
+       if (!of_property_read_u32(np, "nvidia,h-ref-to-sync", &temp)) {
+               modes->h_ref_to_sync = temp;
+       } else {
+               OF_DC_LOG("of h_ref_to_sync %d\n", temp);
+               goto parse_modes_fail;
+       }
+       if (!of_property_read_u32(np, "nvidia,v-ref-to-sync", &temp)) {
+               modes->v_ref_to_sync = temp;
+       } else {
+               OF_DC_LOG("of v_ref_to_sync %d\n", temp);
+               goto parse_modes_fail;
+       }
+       if (!of_property_read_u32(np, "hsync-len", &temp)) {
+               modes->h_sync_width = temp;
+       } else {
+               OF_DC_LOG("of h_sync_width %d\n", temp);
+               goto parse_modes_fail;
+       }
+       if (!of_property_read_u32(np, "vsync-len", &temp)) {
+               modes->v_sync_width = temp;
+       } else {
+               OF_DC_LOG("of v_sync_width %d\n", temp);
+               goto parse_modes_fail;
+       }
+       if (!of_property_read_u32(np, "hback-porch", &temp)) {
+               modes->h_back_porch = temp;
+       } else {
+               OF_DC_LOG("of h_back_porch %d\n", temp);
+               goto parse_modes_fail;
+       }
+       if (!of_property_read_u32(np, "vback-porch", &temp)) {
+               modes->v_back_porch = temp;
+       } else {
+               OF_DC_LOG("of v_back_porch %d\n", temp);
+               goto parse_modes_fail;
+       }
+       if (!of_property_read_u32(np, "hactive", &temp)) {
+               modes->h_active = temp;
+       } else {
+               OF_DC_LOG("of h_active %d\n", temp);
+               goto parse_modes_fail;
+       }
+       if (!of_property_read_u32(np, "vactive", &temp)) {
+               modes->v_active = temp;
+       } else {
+               OF_DC_LOG("of v_active %d\n", temp);
+               goto parse_modes_fail;
+       }
+       if (!of_property_read_u32(np, "hfront-porch", &temp)) {
+               modes->h_front_porch = temp;
+       } else {
+               OF_DC_LOG("of h_front_porch %d\n", temp);
+               goto parse_modes_fail;
+       }
+       if (!of_property_read_u32(np, "vfront-porch", &temp)) {
+               modes->v_front_porch = temp;
+       } else {
+               OF_DC_LOG("of v_front_porch %d\n", temp);
+               goto parse_modes_fail;
+       }
+       return 0;
+parse_modes_fail:
+       pr_err("a mode parameter parse fail!\n");
+       return -EINVAL;
+}
+
+#ifdef CONFIG_TEGRA_DC_CMU
+static int parse_cmu_data(struct device_node *np,
+       struct tegra_dc_cmu *cmu)
+{
+       u16 *csc_parse;
+       u8 *addr_cmu_lut2;
+       struct property *prop;
+       const __be32 *p;
+       u32 u;
+       int csc_count = 0;
+       int lut2_count = 0;
+
+       memcpy(cmu, &default_cmu, sizeof(struct tegra_dc_cmu));
+
+       csc_parse = &(cmu->csc.krr);
+       addr_cmu_lut2 = &(cmu->lut2[0]);
+
+       of_property_for_each_u32(np, "nvidia,cmu-csc", prop, p, u)
+               csc_count++;
+       if (csc_count >
+               (sizeof(cmu->csc) / sizeof(cmu->csc.krr))) {
+               pr_err("cmu csc overflow\n");
+               return -EINVAL;
+       } else {
+               of_property_for_each_u32(np,
+                       "nvidia,cmu-csc", prop, p, u) {
+                       OF_DC_LOG("cmu csc 0x%x\n", u);
+                       *(csc_parse++) = (u16)u;
+               }
+       }
+
+       of_property_for_each_u32(np, "nvidia,cmu-lut2", prop, p, u)
+               lut2_count++;
+
+       if (lut2_count >
+               (sizeof(cmu->lut2) / sizeof(cmu->lut2[0]))) {
+               pr_err("cmu lut2 overflow\n");
+               return -EINVAL;
+       } else {
+               of_property_for_each_u32(np, "nvidia,cmu-lut2",
+                       prop, p, u) {
+                       /* OF_DC_LOG("cmu lut2 0x%x\n", u); */
+                       *(addr_cmu_lut2++) = (u8)u;
+               }
+       }
+       return 0;
+}
+#endif
+
+static int parse_fb_info(struct device_node *np, struct tegra_fb_data *fb)
+{
+       u32 temp;
+       const char *temp_str0;
+
+       /*
+        * set fb->win to 0 in defalut
+        */
+       fb->win = 0;
+
+       if (!of_property_read_u32(np, "nvidia,fb-bpp", &temp)) {
+               fb->bits_per_pixel = (int)temp;
+               OF_DC_LOG("fb bpp %d\n", fb->bits_per_pixel);
+       } else {
+               goto fail_fb_info;
+       }
+       if (!of_property_read_string(np, "nvidia,fb-flags", &temp_str0)) {
+               if (!strncmp(temp_str0, "flip_on_probe", strlen(temp_str0))) {
+                       fb->flags = TEGRA_FB_FLIP_ON_PROBE;
+                       OF_DC_LOG("fb flip on probe\n");
+               } else {
+                       pr_err("invalid fb_flags\n");
+                       return -EINVAL;
+               }
+       }
+       if (!of_property_read_u32(np, "nvidia,fb-xres", &temp)) {
+               fb->xres = (int)temp;
+               OF_DC_LOG("fb xres %d\n", fb->xres);
+       } else {
+               goto fail_fb_info;
+       }
+       if (!of_property_read_u32(np, "nvidia,fb-yres", &temp)) {
+               fb->yres = (int)temp;
+               OF_DC_LOG("fb yres %d\n", fb->yres);
+       } else {
+               goto fail_fb_info;
+       }
+       return 0;
+
+fail_fb_info:
+       pr_err("%s: a parse error\n", __func__);
+       return -EINVAL;
+}
+
+static int parse_dsi_settings(struct platform_device *ndev,
+       struct device_node *np_dsi, struct tegra_dsi_out *dsi)
+{
+       const char *temp_str0;
+       u32 temp;
+
+       /*
+        * tegra114 DSI Version is 1
+        */
+       dsi->controller_vs = DSI_VS_1;
+
+       if (!of_property_read_u32(np_dsi,
+               "nvidia,dsi-n-data-lanes", &temp)) {
+               dsi->n_data_lanes = (u8)temp;
+               OF_DC_LOG("n data lanes %d\n", dsi->n_data_lanes);
+       }
+       if (!of_property_read_string(np_dsi,
+                       "nvidia,dsi-video-burst-mode", &temp_str0)) {
+               if (!strncmp(temp_str0, "none_burst", strlen(temp_str0))) {
+                       dsi->video_burst_mode =
+                               TEGRA_DSI_VIDEO_NONE_BURST_MODE;
+               } else if (!strncmp(temp_str0, "none_burst_sync_end",
+                                       strlen(temp_str0))) {
+                       dsi->video_burst_mode =
+                               TEGRA_DSI_VIDEO_NONE_BURST_MODE_WITH_SYNC_END;
+               } else if (!strncmp(temp_str0, "burst_lowest_speed",
+                                       strlen(temp_str0))) {
+                       dsi->video_burst_mode =
+                               TEGRA_DSI_VIDEO_BURST_MODE_LOWEST_SPEED;
+               } else if (!strncmp(temp_str0, "burst_low_speed",
+                                       strlen(temp_str0))) {
+                       dsi->video_burst_mode =
+                               TEGRA_DSI_VIDEO_BURST_MODE_LOW_SPEED;
+               } else if (!strncmp(temp_str0, "burst_mid_speed",
+                                       strlen(temp_str0))) {
+                       dsi->video_burst_mode =
+                               TEGRA_DSI_VIDEO_BURST_MODE_MEDIUM_SPEED;
+               } else if (!strncmp(temp_str0, "burst_fast_speed",
+                                       strlen(temp_str0))) {
+                       dsi->video_burst_mode =
+                               TEGRA_DSI_VIDEO_BURST_MODE_FAST_SPEED;
+               } else if (!strncmp(temp_str0, "burst_fastest_speed",
+                                       strlen(temp_str0))) {
+                       dsi->video_burst_mode =
+                               TEGRA_DSI_VIDEO_BURST_MODE_FASTEST_SPEED;
+               } else {
+                       pr_err("invalid dsi video burst mode\n");
+                       return -EINVAL;
+               }
+       }
+
+       if (!of_property_read_string(np_dsi,
+               "nvidia,dsi-pixel-format", &temp_str0)) {
+               if (!strncmp(temp_str0, "24_p", strlen(temp_str0))) {
+                       dsi->pixel_format =
+                               TEGRA_DSI_PIXEL_FORMAT_24BIT_P;
+               } else if (!strncmp(temp_str0, "18_p", strlen(temp_str0))) {
+                       dsi->pixel_format =
+                               TEGRA_DSI_PIXEL_FORMAT_18BIT_P;
+               } else if (!strncmp(temp_str0, "18_np", strlen(temp_str0))) {
+                       dsi->pixel_format =
+                               TEGRA_DSI_PIXEL_FORMAT_18BIT_NP;
+               } else if (!strncmp(temp_str0, "16_p", strlen(temp_str0))) {
+                       dsi->pixel_format =
+                               TEGRA_DSI_PIXEL_FORMAT_16BIT_P;
+               } else {
+                       pr_err("invalid dsi pixel format\n");
+                       return -EINVAL;
+               }
+       }
+       if (!of_property_read_u32(np_dsi,
+               "nvidia,dsi-ref-rate", &temp)) {
+               dsi->refresh_rate = (u8)temp;
+               OF_DC_LOG("dsi refresh rate %d\n", dsi->refresh_rate);
+       }
+       if (!of_property_read_string(np_dsi,
+               "nvidia,dsi-virtual-ch", &temp_str0)) {
+               if (!strncmp(temp_str0, "vc0", strlen(temp_str0))) {
+                       dsi->virtual_channel =
+                               TEGRA_DSI_VIRTUAL_CHANNEL_0;
+               } else if (!strncmp(temp_str0, "vc1", strlen(temp_str0))) {
+                       dsi->virtual_channel =
+                               TEGRA_DSI_VIRTUAL_CHANNEL_1;
+               } else if (!strncmp(temp_str0, "vc2", strlen(temp_str0))) {
+                       dsi->virtual_channel =
+                               TEGRA_DSI_VIRTUAL_CHANNEL_2;
+               } else if (!strncmp(temp_str0, "vc3", strlen(temp_str0))) {
+                       dsi->virtual_channel =
+                               TEGRA_DSI_VIRTUAL_CHANNEL_3;
+               } else {
+                       pr_err("invalid dsi virtual ch\n");
+                       return -EINVAL;
+               }
+       }
+       if (!of_property_read_u32(np_dsi, "nvidia,dsi-instance", &temp)) {
+               dsi->dsi_instance = (u8)temp;
+               OF_DC_LOG("dsi instance %d\n", dsi->dsi_instance);
+       }
+       if (!of_property_read_u32(np_dsi,
+               "nvidia,dsi-panel-reset", &temp)) {
+               dsi->panel_reset = (u8)temp;
+               OF_DC_LOG("dsi panel reset %d\n", dsi->panel_reset);
+       }
+       if (!of_property_read_u32(np_dsi,
+               "nvidia,dsi-power-saving-suspend", &temp)) {
+               dsi->power_saving_suspend = (bool)temp;
+               OF_DC_LOG("dsi power saving suspend %d\n",
+                       dsi->power_saving_suspend);
+       }
+       if (!of_property_read_string(np_dsi,
+               "nvidia,dsi-video-data-type", &temp_str0)) {
+               if (!strncmp(temp_str0, "video", strlen(temp_str0))) {
+                       dsi->video_data_type =
+                               TEGRA_DSI_VIDEO_TYPE_VIDEO_MODE;
+               } else if (!strncmp(temp_str0, "cmd", strlen(temp_str0))) {
+                       dsi->video_data_type =
+                               TEGRA_DSI_VIDEO_TYPE_COMMAND_MODE;
+               } else {
+                       pr_err("invalid dsi video data type\n");
+                       return -EINVAL;
+               }
+       }
+       if (!of_property_read_string(np_dsi,
+               "nvidia,dsi-video-clk-mode", &temp_str0)) {
+               if (!strncmp(temp_str0, "txonly", strlen(temp_str0))) {
+                       dsi->video_clock_mode =
+                               TEGRA_DSI_VIDEO_CLOCK_TX_ONLY;
+               } else if (!strncmp(temp_str0,
+                       "continuous", strlen(temp_str0))) {
+                       dsi->video_clock_mode =
+                               TEGRA_DSI_VIDEO_CLOCK_CONTINUOUS;
+               } else {
+                       pr_err("invalid dsi video clk mode\n");
+                       return -EINVAL;
+               }
+       }
+
+       if (!of_property_read_u32(np_dsi,
+               "nvidia,dsi-phy-hsdexit", &temp)) {
+               dsi->phy_timing.t_hsdexit_ns = (u16)temp;
+               OF_DC_LOG("phy t_hsdexit_ns %d\n",
+                       dsi->phy_timing.t_hsdexit_ns);
+       }
+
+       if (!of_property_read_u32(np_dsi,
+               "nvidia,dsi-phy-hstrail", &temp)) {
+               dsi->phy_timing.t_hstrail_ns = (u16)temp;
+               OF_DC_LOG("phy t_hstrail_ns %d\n",
+                       dsi->phy_timing.t_hstrail_ns);
+       }
+
+       if (!of_property_read_u32(np_dsi,
+               "nvidia,dsi-phy-datzero", &temp)) {
+               dsi->phy_timing.t_datzero_ns = (u16)temp;
+               OF_DC_LOG("phy t_datzero_ns %d\n",
+                       dsi->phy_timing.t_datzero_ns);
+       }
+
+       if (!of_property_read_u32(np_dsi,
+               "nvidia,dsi-phy-hsprepare", &temp)) {
+               dsi->phy_timing.t_hsprepare_ns = (u16)temp;
+               OF_DC_LOG("phy t_hsprepare_ns %d\n",
+                       dsi->phy_timing.t_hsprepare_ns);
+       }
+
+       if (!of_property_read_u32(np_dsi,
+               "nvidia,dsi-phy-clktrail", &temp)) {
+               dsi->phy_timing.t_clktrail_ns = (u16)temp;
+               OF_DC_LOG("phy t_clktrail_ns %d\n",
+                       dsi->phy_timing.t_clktrail_ns);
+       }
+
+       if (!of_property_read_u32(np_dsi,
+               "nvidia,dsi-phy-clkpost", &temp)) {
+               dsi->phy_timing.t_clkpost_ns = (u16)temp;
+               OF_DC_LOG("phy t_clkpost_ns %d\n",
+                       dsi->phy_timing.t_clkpost_ns);
+       }
+
+       if (!of_property_read_u32(np_dsi,
+               "nvidia,dsi-phy-clkzero", &temp)) {
+               dsi->phy_timing.t_clkzero_ns = (u16)temp;
+               OF_DC_LOG("phy t_clkzero_ns %d\n",
+                       dsi->phy_timing.t_clkzero_ns);
+       }
+
+       if (!of_property_read_u32(np_dsi,
+               "nvidia,dsi-phy-tlpx", &temp)) {
+               dsi->phy_timing.t_tlpx_ns = (u16)temp;
+               OF_DC_LOG("phy t_tlpx_ns %d\n",
+                       dsi->phy_timing.t_tlpx_ns);
+       }
+
+       if (!of_property_read_u32(np_dsi,
+               "nvidia,dsi-phy-clkprepare", &temp)) {
+               dsi->phy_timing.t_clkprepare_ns = (u16)temp;
+               OF_DC_LOG("phy t_clkprepare_ns %d\n",
+                       dsi->phy_timing.t_clkprepare_ns);
+       }
+
+       if (!of_property_read_u32(np_dsi,
+               "nvidia,dsi-phy-clkpre", &temp)) {
+               dsi->phy_timing.t_clkpre_ns = (u16)temp;
+               OF_DC_LOG("phy t_clkpre_ns %d\n",
+                       dsi->phy_timing.t_clkpre_ns);
+       }
+
+       if (!of_property_read_u32(np_dsi,
+               "nvidia,dsi-phy-wakeup", &temp)) {
+               dsi->phy_timing.t_wakeup_ns = (u16)temp;
+               OF_DC_LOG("phy t_wakeup_ns %d\n",
+                       dsi->phy_timing.t_wakeup_ns);
+       }
+
+       if (!of_property_read_u32(np_dsi,
+               "nvidia,dsi-phy-taget", &temp)) {
+               dsi->phy_timing.t_taget_ns = (u16)temp;
+               OF_DC_LOG("phy t_taget_ns %d\n",
+                       dsi->phy_timing.t_taget_ns);
+       }
+
+       if (!of_property_read_u32(np_dsi,
+               "nvidia,dsi-phy-tasure", &temp)) {
+               dsi->phy_timing.t_tasure_ns = (u16)temp;
+               OF_DC_LOG("phy t_tasure_ns %d\n",
+                       dsi->phy_timing.t_tasure_ns);
+       }
+
+       if (!of_property_read_u32(np_dsi,
+               "nvidia,dsi-phy-tago", &temp)) {
+               dsi->phy_timing.t_tago_ns = (u16)temp;
+               OF_DC_LOG("phy t_tago_ns %d\n",
+                       dsi->phy_timing.t_tago_ns);
+       }
+
+       return 0;
+}
+
+static int dc_hdmi_out_enable(struct device *dev)
+{
+       int err;
+       int i = 0;
+       struct property *prop;
+       const char *regulator;
+
+       struct device_node *np_hdmi =
+               of_find_compatible_node(NULL, NULL, "nvidia,tegra114-hdmi");
+
+       if (!np_hdmi) {
+               pr_info("%s: no hdmi node\n", __func__);
+               return 0;
+       }
+
+       of_property_for_each_string(np_hdmi, "nvidia,regulators",
+               prop, regulator) {
+               if (i >= HDMI_REGULATORS_COUNT)
+                       return 0;
+               if (!of_regulators_dc1[i]) {
+                       of_regulators_dc1[i] = regulator_get(dev, regulator);
+                       if (IS_ERR_OR_NULL(of_regulators_dc1[i])) {
+                               pr_err("hdmi: couldn't get regulator\n");
+                               of_regulators_dc1[i] = NULL;
+                               return PTR_ERR(of_regulators_dc1[i]);
+                       }
+               }
+               err = regulator_enable(of_regulators_dc1[i]);
+               if (err < 0) {
+                       pr_err("hdmi: couldn't enable regulator avdd_hdmi\n");
+                       return err;
+               }
+               i++;
+       }
+       return 0;
+}
+
+static int dc_hdmi_out_disable(void)
+{
+       int i;
+       for (i = 0 ; i < HDMI_REGULATORS_COUNT; i++) {
+               if (of_regulators_dc1[i]) {
+                       regulator_disable(of_regulators_dc1[i]);
+                       regulator_put(of_regulators_dc1[i]);
+                       of_regulators_dc1[i] = NULL;
+               }
+       }
+       return 0;
+}
+
+static int dc_hdmi_hotplug_init(struct device *dev)
+{
+       int err;
+       int i = 0;
+       struct property *prop;
+       const char *regulator;
+
+       struct device_node *np_hdmi =
+               of_find_compatible_node(NULL, NULL, "nvidia,tegra114-hdmi");
+
+       if (!np_hdmi) {
+               pr_info("%s: no hdmi node\n", __func__);
+               return 0;
+       }
+
+       of_property_for_each_string(np_hdmi, "nvidia,regulators",
+               prop, regulator) {
+               if (i < HDMI_REGULATORS_COUNT) {
+                       i++;
+                       continue;
+               }
+               if (!of_regulators_dc1[i]) {
+                       of_regulators_dc1[i] = regulator_get(dev, regulator);
+                       if (IS_ERR_OR_NULL(of_regulators_dc1[i])) {
+                               pr_err("hdmi: couldn't get regulator\n");
+                               of_regulators_dc1[i] = NULL;
+                               return PTR_ERR(of_regulators_dc1[i]);
+                       }
+               }
+               err = regulator_enable(of_regulators_dc1[i]);
+               if (err < 0) {
+                       pr_err("hdmi: couldn't enable regulator avdd_hdmi 5v0\n");
+                       return err;
+               }
+       }
+       return 0;
+}
+
+static int dc_hdmi_postsuspend(void)
+{
+       if (of_regulators_dc1[HDMI_REGS_TOTAL - 1]) {
+               regulator_disable(of_regulators_dc1[HDMI_REGS_TOTAL - 1]);
+               regulator_put(of_regulators_dc1[HDMI_REGS_TOTAL - 1]);
+               of_regulators_dc1[HDMI_REGS_TOTAL - 1] = NULL;
+       }
+       return 0;
+}
+
+static bool typical_prop_search(struct device_node *np, const char **prop)
+{
+       int iprop;
+       const char *temp_str;
+
+       for (iprop = 0; iprop < TYPICAL_SEARCH_ITER; iprop++) {
+               if (!of_property_read_string(np, prop[iprop], &temp_str))
+                       return true;
+       }
+       return false;
+}
+
+struct tegra_dc_platform_data
+               *of_dc_parse_platform_data(struct platform_device *ndev)
+{
+       struct tegra_dc_platform_data *pdata;
+       struct tegra_dc_platform_data *temp_pdata = NULL;
+       struct device_node *np = ndev->dev.of_node;
+       struct device_node *np_dsi = NULL;
+       struct device_node *timings_np = NULL;
+       struct device_node *fb_np = NULL;
+       struct device_node *sd_np = NULL;
+       struct device_node *default_out_np = NULL;
+       struct device_node *entry = NULL;
+       struct device_node *pnode = NULL;
+#ifdef CONFIG_TEGRA_DC_CMU
+       struct device_node *cmu_np = NULL;
+#endif
+       const char *temp_str0;
+       int err;
+       int np_dsi_okay = 0;
+       u32 temp;
+       bool prop_searched;
+       struct of_tegra_dc_data *of_pdata = NULL;
+       struct of_tegra_lcd_devdata *lcd_dev_data = NULL;
+
+       /*
+        * Memory for pdata, pdata->default_out, pdata->fb
+        * need to be allocated in defalut
+        * since it is expected data for these needs to be
+        * parsed from DTB.
+        */
+       pdata = devm_kzalloc(&ndev->dev,
+               sizeof(struct tegra_dc_platform_data), GFP_KERNEL);
+       if (!pdata) {
+               dev_err(&ndev->dev, "not enough memory\n");
+               goto fail_parse;
+       }
+
+       pdata->default_out = devm_kzalloc(&ndev->dev,
+               sizeof(struct tegra_dc_out), GFP_KERNEL);
+       if (!pdata->default_out) {
+               dev_err(&ndev->dev, "not enough memory\n");
+               goto fail_parse;
+       }
+
+       pdata->fb = devm_kzalloc(&ndev->dev,
+               sizeof(struct tegra_fb_data), GFP_KERNEL);
+       if (!pdata->fb) {
+               dev_err(&ndev->dev, "not enough memory\n");
+               goto fail_parse;
+       }
+
+       timings_np = of_find_node_by_name(np, "display-timings");
+       if (!timings_np) {
+               pr_warn("%s: could not find display-timings node\n",
+                       __func__);
+       } else {
+               pdata->default_out->n_modes =
+                       of_get_child_count(timings_np);
+               if (pdata->default_out->n_modes == 0) {
+                       /*
+                        * Should never happen !
+                        */
+                       dev_err(&ndev->dev, "no timing given\n");
+                       goto fail_parse;
+               }
+               pdata->default_out->modes = devm_kzalloc(&ndev->dev,
+                       pdata->default_out->n_modes *
+                       sizeof(struct tegra_dc_mode), GFP_KERNEL);
+               if (!pdata->default_out->modes) {
+                       dev_err(&ndev->dev, "not enough memory\n");
+                       goto fail_parse;
+               }
+       }
+       sd_np = of_find_node_by_name(np, "smartdimmer");
+       if (!sd_np) {
+               pr_warn("%s: could not find SD settings node\n",
+                       __func__);
+       } else {
+               prop_searched = typical_prop_search(sd_np,
+                               typical_sd_settings);
+               if (prop_searched) {
+                       pdata->default_out->sd_settings =
+                               devm_kzalloc(&ndev->dev,
+                               sizeof(struct tegra_dc_sd_settings),
+                               GFP_KERNEL);
+                       if (!pdata->default_out->sd_settings) {
+                               dev_err(&ndev->dev, "not enough memory\n");
+                               goto fail_parse;
+                       }
+               } else {
+                       dev_err(&ndev->dev, "sd_settings: No data in node\n");
+                       goto fail_parse;
+               }
+       }
+
+#ifdef CONFIG_TEGRA_DC_CMU
+       cmu_np = of_find_node_by_name(np, "cmu");
+       if (!cmu_np) {
+               pr_warn("%s: could not find cmu node\n",
+                       __func__);
+       } else {
+               prop_searched = typical_prop_search(cmu_np, typical_cmu);
+
+               if (prop_searched) {
+                       pdata->cmu = devm_kzalloc(&ndev->dev,
+                               sizeof(struct tegra_dc_cmu), GFP_KERNEL);
+                       if (!pdata->cmu) {
+                               dev_err(&ndev->dev, "not enough memory\n");
+                               goto fail_parse;
+                       }
+               } else {
+                       dev_err(&ndev->dev, "cmu: No data in node\n");
+                       goto fail_parse;
+               }
+       }
+#endif
+
+       /*
+        * determine dc out type
+        */
+       default_out_np = of_find_node_by_name(np, "dc-default-out");
+       if (!default_out_np) {
+               pr_warn("%s: could not find dc-default-out node\n",
+                       __func__);
+       } else {
+               err = parse_dc_default_out(default_out_np, pdata->default_out);
+               if (err)
+                       goto fail_parse;
+       }
+       temp_pdata = (struct tegra_dc_platform_data *)ndev->dev.platform_data;
+       of_pdata = &(temp_pdata->of_data);
+       if (pdata->default_out->type == TEGRA_DC_OUT_DSI) {
+               struct device *panel_dev = NULL;
+
+               of_pdata->dc_controller = DC_CONTROLLER_0;
+
+               np_dsi = of_find_compatible_node(NULL,
+                               NULL, "nvidia,tegra114-dsi");
+
+               if (np_dsi)
+                       np_dsi_okay = of_device_is_available(np_dsi);
+
+               if (np_dsi_okay)
+                       prop_searched =
+                               typical_prop_search(np_dsi, typical_dsi_out);
+
+               if (np_dsi_okay && prop_searched) {
+                       pdata->default_out->dsi = devm_kzalloc(&ndev->dev,
+                               sizeof(struct tegra_dsi_out), GFP_KERNEL);
+                       if (!pdata->default_out->dsi) {
+                               dev_err(&ndev->dev, "not enough memory\n");
+                               goto fail_parse;
+                       }
+               }
+
+               if (np_dsi_okay)
+                       pnode = of_parse_phandle(np_dsi, "nvidia,panel", 0);
+
+               if (pnode)
+                       panel_dev = lcd_devdata_to_dc_callback_run(pnode);
+
+               if (panel_dev) {
+                       lcd_dev_data = (struct of_tegra_lcd_devdata *)
+                               dev_get_drvdata(panel_dev);
+                       pdata->default_out->enable = lcd_dev_data->enable;
+                       pdata->default_out->postpoweron =
+                               lcd_dev_data->postpoweron;
+                       pdata->default_out->prepoweroff =
+                               lcd_dev_data->prepoweroff;
+                       pdata->default_out->disable = lcd_dev_data->disable;
+               }
+               if (lcd_dev_data) {
+                       pdata->default_out->dsi->dsi_init_cmd =
+                               lcd_dev_data->dsi_init_cmd;
+                       pdata->default_out->dsi->n_init_cmd =
+                               lcd_dev_data->n_init_cmd;
+
+                       pdata->default_out->dsi->dsi_early_suspend_cmd =
+                               lcd_dev_data->dsi_early_suspend_cmd;
+                       pdata->default_out->dsi->n_early_suspend_cmd =
+                               lcd_dev_data->n_early_suspend_cmd;
+
+                       pdata->default_out->dsi->dsi_late_resume_cmd =
+                               lcd_dev_data->dsi_late_resume_cmd;
+                       pdata->default_out->dsi->n_late_resume_cmd =
+                               lcd_dev_data->n_late_resume_cmd;
+
+                       pdata->default_out->dsi->dsi_suspend_cmd =
+                               lcd_dev_data->dsi_suspend_cmd;
+                       pdata->default_out->dsi->n_suspend_cmd =
+                               lcd_dev_data->n_suspend_cmd;
+
+                       pdata->default_out->dsi->pkt_seq =
+                               lcd_dev_data->pkt_seq;
+               }
+       } else if (pdata->default_out->type == TEGRA_DC_OUT_HDMI) {
+               of_pdata->dc_controller = DC_CONTROLLER_1;
+               pdata->default_out->enable = dc_hdmi_out_enable;
+               pdata->default_out->disable = dc_hdmi_out_disable;
+               pdata->default_out->hotplug_init = dc_hdmi_hotplug_init;
+               pdata->default_out->postsuspend = dc_hdmi_postsuspend;
+       }
+
+       /*
+        * parse sd_settings values
+        */
+       if (pdata->default_out->sd_settings != NULL) {
+               err = parse_sd_settings(sd_np, pdata->default_out->sd_settings);
+               if (err)
+                       goto fail_parse;
+       }
+
+       if (pdata->default_out->modes != NULL) {
+               struct tegra_dc_mode *cur_mode
+                       = pdata->default_out->modes;
+               for_each_child_of_node(timings_np, entry) {
+                       err = parse_modes(entry, cur_mode);
+                       if (err)
+                               goto fail_parse;
+                       cur_mode++;
+               }
+       }
+
+#ifdef CONFIG_TEGRA_DC_CMU
+       if (pdata->cmu != NULL) {
+               err = parse_cmu_data(cmu_np, pdata->cmu);
+               if (err)
+                       goto fail_parse;
+       }
+#endif
+
+       if (pdata->default_out->dsi) {
+               /* It happens in case of TEGRA_DC_OUT_DSI only */
+               err = parse_dsi_settings(ndev, np_dsi,
+                       pdata->default_out->dsi);
+               if (err)
+                       goto fail_parse;
+       }
+
+       fb_np = of_find_node_by_name(np, "framebuffer-data");
+       if (!fb_np) {
+               pr_err("%s: err, No framebuffer-data\n",
+                       __func__);
+               goto fail_parse;
+       } else {
+               err = parse_fb_info(fb_np, pdata->fb);
+               if (err)
+                       goto fail_parse;
+       }
+
+       if (!of_property_read_string(np, "nvidia,dc-flags", &temp_str0)) {
+               if (!strncmp(temp_str0, "dc_flag_en", strlen(temp_str0))) {
+                       pdata->flags = TEGRA_DC_FLAG_ENABLED;
+                       OF_DC_LOG("dc flag en\n");
+               }
+       }
+       if (!of_property_read_u32(np, "nvidia,emc-clk-rate", &temp)) {
+               pdata->emc_clk_rate = (unsigned long)temp;
+               OF_DC_LOG("emc clk rate %lu\n", pdata->emc_clk_rate);
+       }
+#ifdef CONFIG_TEGRA_DC_CMU
+       if (!of_property_read_u32(np, "nvidia,cmu-enable", &temp)) {
+               pdata->cmu_enable = (bool)temp;
+               OF_DC_LOG("cmu enable %d\n", pdata->cmu_enable);
+       } else {
+               pdata->cmu_enable = false;
+       }
+#endif
+       return pdata;
+
+fail_parse:
+       return NULL;
+}
+#else
+struct tegra_dc_platform_data
+               *of_dc_parse_platform_data(struct platform_device *ndev)
+{
+       return NULL;
+}
+#endif