diff options
author | Archit Taneja <archit@ti.com> | 2011-05-16 05:47:08 -0400 |
---|---|---|
committer | Tomi Valkeinen <tomi.valkeinen@ti.com> | 2011-05-16 06:31:09 -0400 |
commit | 75d7247c07d27d046323504e2dbca5b3e94fbece (patch) | |
tree | 69b545fb4181fbd9fd50dd2a36cb68eab731e443 /drivers/video/omap2 | |
parent | 49dbf5892fc67466ac2780c1d42d8a02726f5538 (diff) |
OMAP: DSS2: DSI: Get number of DSI data lanes using DSI_GNQ register
On OMAP3, the DSI module has 2 data lanes. On OMAP4, DSI1 has 4 data lanes
and DSI2 has 2 data lanes. Introduce function dsi_get_num_data_lanes() which
returns the number of data lanes on the dsi interface, introduce function
dsi_get_num_data_lanes_dssdev() which returns the number of data lanes used by
the omap_dss_device connected to the lanes.
Use the DSI_GNQ register on OMAP4 to get the number of data lanes, modify
dsi.c to use the number of lanes and the extra data lanes on DSI1.
Signed-off-by: Archit Taneja <archit@ti.com>
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
Diffstat (limited to 'drivers/video/omap2')
-rw-r--r-- | drivers/video/omap2/dss/dsi.c | 97 | ||||
-rw-r--r-- | drivers/video/omap2/dss/dss_features.c | 3 | ||||
-rw-r--r-- | drivers/video/omap2/dss/dss_features.h | 1 |
3 files changed, 91 insertions, 10 deletions
diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c index f04244bba76..784677d088f 100644 --- a/drivers/video/omap2/dss/dsi.c +++ b/drivers/video/omap2/dss/dsi.c | |||
@@ -59,6 +59,7 @@ struct dsi_reg { u16 idx; }; | |||
59 | #define DSI_IRQSTATUS DSI_REG(0x0018) | 59 | #define DSI_IRQSTATUS DSI_REG(0x0018) |
60 | #define DSI_IRQENABLE DSI_REG(0x001C) | 60 | #define DSI_IRQENABLE DSI_REG(0x001C) |
61 | #define DSI_CTRL DSI_REG(0x0040) | 61 | #define DSI_CTRL DSI_REG(0x0040) |
62 | #define DSI_GNQ DSI_REG(0x0044) | ||
62 | #define DSI_COMPLEXIO_CFG1 DSI_REG(0x0048) | 63 | #define DSI_COMPLEXIO_CFG1 DSI_REG(0x0048) |
63 | #define DSI_COMPLEXIO_IRQ_STATUS DSI_REG(0x004C) | 64 | #define DSI_COMPLEXIO_IRQ_STATUS DSI_REG(0x004C) |
64 | #define DSI_COMPLEXIO_IRQ_ENABLE DSI_REG(0x0050) | 65 | #define DSI_COMPLEXIO_IRQ_ENABLE DSI_REG(0x0050) |
@@ -238,6 +239,10 @@ enum dsi_lane { | |||
238 | DSI_DATA1_N = 1 << 3, | 239 | DSI_DATA1_N = 1 << 3, |
239 | DSI_DATA2_P = 1 << 4, | 240 | DSI_DATA2_P = 1 << 4, |
240 | DSI_DATA2_N = 1 << 5, | 241 | DSI_DATA2_N = 1 << 5, |
242 | DSI_DATA3_P = 1 << 6, | ||
243 | DSI_DATA3_N = 1 << 7, | ||
244 | DSI_DATA4_P = 1 << 8, | ||
245 | DSI_DATA4_N = 1 << 9, | ||
241 | }; | 246 | }; |
242 | 247 | ||
243 | struct dsi_update_region { | 248 | struct dsi_update_region { |
@@ -326,6 +331,8 @@ struct dsi_data { | |||
326 | unsigned long fint_min, fint_max; | 331 | unsigned long fint_min, fint_max; |
327 | unsigned long lpdiv_max; | 332 | unsigned long lpdiv_max; |
328 | 333 | ||
334 | int num_data_lanes; | ||
335 | |||
329 | unsigned scp_clk_refcount; | 336 | unsigned scp_clk_refcount; |
330 | }; | 337 | }; |
331 | 338 | ||
@@ -2001,10 +2008,39 @@ static int dsi_cio_power(struct platform_device *dsidev, | |||
2001 | return 0; | 2008 | return 0; |
2002 | } | 2009 | } |
2003 | 2010 | ||
2011 | /* Number of data lanes present on DSI interface */ | ||
2012 | static inline int dsi_get_num_data_lanes(struct platform_device *dsidev) | ||
2013 | { | ||
2014 | /* DSI on OMAP3 doesn't have register DSI_GNQ, set number | ||
2015 | * of data lanes as 2 by default */ | ||
2016 | if (dss_has_feature(FEAT_DSI_GNQ)) | ||
2017 | return REG_GET(dsidev, DSI_GNQ, 11, 9); /* NB_DATA_LANES */ | ||
2018 | else | ||
2019 | return 2; | ||
2020 | } | ||
2021 | |||
2022 | /* Number of data lanes used by the dss device */ | ||
2023 | static inline int dsi_get_num_data_lanes_dssdev(struct omap_dss_device *dssdev) | ||
2024 | { | ||
2025 | int num_data_lanes = 0; | ||
2026 | |||
2027 | if (dssdev->phy.dsi.data1_lane != 0) | ||
2028 | num_data_lanes++; | ||
2029 | if (dssdev->phy.dsi.data2_lane != 0) | ||
2030 | num_data_lanes++; | ||
2031 | if (dssdev->phy.dsi.data3_lane != 0) | ||
2032 | num_data_lanes++; | ||
2033 | if (dssdev->phy.dsi.data4_lane != 0) | ||
2034 | num_data_lanes++; | ||
2035 | |||
2036 | return num_data_lanes; | ||
2037 | } | ||
2038 | |||
2004 | static void dsi_set_lane_config(struct omap_dss_device *dssdev) | 2039 | static void dsi_set_lane_config(struct omap_dss_device *dssdev) |
2005 | { | 2040 | { |
2006 | struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); | 2041 | struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); |
2007 | u32 r; | 2042 | u32 r; |
2043 | int num_data_lanes_dssdev = dsi_get_num_data_lanes_dssdev(dssdev); | ||
2008 | 2044 | ||
2009 | int clk_lane = dssdev->phy.dsi.clk_lane; | 2045 | int clk_lane = dssdev->phy.dsi.clk_lane; |
2010 | int data1_lane = dssdev->phy.dsi.data1_lane; | 2046 | int data1_lane = dssdev->phy.dsi.data1_lane; |
@@ -2020,6 +2056,20 @@ static void dsi_set_lane_config(struct omap_dss_device *dssdev) | |||
2020 | r = FLD_MOD(r, data1_pol, 7, 7); | 2056 | r = FLD_MOD(r, data1_pol, 7, 7); |
2021 | r = FLD_MOD(r, data2_lane, 10, 8); | 2057 | r = FLD_MOD(r, data2_lane, 10, 8); |
2022 | r = FLD_MOD(r, data2_pol, 11, 11); | 2058 | r = FLD_MOD(r, data2_pol, 11, 11); |
2059 | if (num_data_lanes_dssdev > 2) { | ||
2060 | int data3_lane = dssdev->phy.dsi.data3_lane; | ||
2061 | int data3_pol = dssdev->phy.dsi.data3_pol; | ||
2062 | |||
2063 | r = FLD_MOD(r, data3_lane, 14, 12); | ||
2064 | r = FLD_MOD(r, data3_pol, 15, 15); | ||
2065 | } | ||
2066 | if (num_data_lanes_dssdev > 3) { | ||
2067 | int data4_lane = dssdev->phy.dsi.data4_lane; | ||
2068 | int data4_pol = dssdev->phy.dsi.data4_pol; | ||
2069 | |||
2070 | r = FLD_MOD(r, data4_lane, 18, 16); | ||
2071 | r = FLD_MOD(r, data4_pol, 19, 19); | ||
2072 | } | ||
2023 | dsi_write_reg(dsidev, DSI_COMPLEXIO_CFG1, r); | 2073 | dsi_write_reg(dsidev, DSI_COMPLEXIO_CFG1, r); |
2024 | 2074 | ||
2025 | /* The configuration of the DSI complex I/O (number of data lanes, | 2075 | /* The configuration of the DSI complex I/O (number of data lanes, |
@@ -2132,14 +2182,20 @@ static void dsi_cio_enable_lane_override(struct omap_dss_device *dssdev, | |||
2132 | enum dsi_lane lanes) | 2182 | enum dsi_lane lanes) |
2133 | { | 2183 | { |
2134 | struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); | 2184 | struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); |
2185 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); | ||
2135 | int clk_lane = dssdev->phy.dsi.clk_lane; | 2186 | int clk_lane = dssdev->phy.dsi.clk_lane; |
2136 | int data1_lane = dssdev->phy.dsi.data1_lane; | 2187 | int data1_lane = dssdev->phy.dsi.data1_lane; |
2137 | int data2_lane = dssdev->phy.dsi.data2_lane; | 2188 | int data2_lane = dssdev->phy.dsi.data2_lane; |
2189 | int data3_lane = dssdev->phy.dsi.data3_lane; | ||
2190 | int data4_lane = dssdev->phy.dsi.data4_lane; | ||
2138 | int clk_pol = dssdev->phy.dsi.clk_pol; | 2191 | int clk_pol = dssdev->phy.dsi.clk_pol; |
2139 | int data1_pol = dssdev->phy.dsi.data1_pol; | 2192 | int data1_pol = dssdev->phy.dsi.data1_pol; |
2140 | int data2_pol = dssdev->phy.dsi.data2_pol; | 2193 | int data2_pol = dssdev->phy.dsi.data2_pol; |
2194 | int data3_pol = dssdev->phy.dsi.data3_pol; | ||
2195 | int data4_pol = dssdev->phy.dsi.data4_pol; | ||
2141 | 2196 | ||
2142 | u32 l = 0; | 2197 | u32 l = 0; |
2198 | u8 lptxscp_start = dsi->num_data_lanes == 2 ? 22 : 26; | ||
2143 | 2199 | ||
2144 | if (lanes & DSI_CLK_P) | 2200 | if (lanes & DSI_CLK_P) |
2145 | l |= 1 << ((clk_lane - 1) * 2 + (clk_pol ? 0 : 1)); | 2201 | l |= 1 << ((clk_lane - 1) * 2 + (clk_pol ? 0 : 1)); |
@@ -2156,17 +2212,28 @@ static void dsi_cio_enable_lane_override(struct omap_dss_device *dssdev, | |||
2156 | if (lanes & DSI_DATA2_N) | 2212 | if (lanes & DSI_DATA2_N) |
2157 | l |= 1 << ((data2_lane - 1) * 2 + (data2_pol ? 1 : 0)); | 2213 | l |= 1 << ((data2_lane - 1) * 2 + (data2_pol ? 1 : 0)); |
2158 | 2214 | ||
2215 | if (lanes & DSI_DATA3_P) | ||
2216 | l |= 1 << ((data3_lane - 1) * 2 + (data3_pol ? 0 : 1)); | ||
2217 | if (lanes & DSI_DATA3_N) | ||
2218 | l |= 1 << ((data3_lane - 1) * 2 + (data3_pol ? 1 : 0)); | ||
2219 | |||
2220 | if (lanes & DSI_DATA4_P) | ||
2221 | l |= 1 << ((data4_lane - 1) * 2 + (data4_pol ? 0 : 1)); | ||
2222 | if (lanes & DSI_DATA4_N) | ||
2223 | l |= 1 << ((data4_lane - 1) * 2 + (data4_pol ? 1 : 0)); | ||
2159 | /* | 2224 | /* |
2160 | * Bits in REGLPTXSCPDAT4TO0DXDY: | 2225 | * Bits in REGLPTXSCPDAT4TO0DXDY: |
2161 | * 17: DY0 18: DX0 | 2226 | * 17: DY0 18: DX0 |
2162 | * 19: DY1 20: DX1 | 2227 | * 19: DY1 20: DX1 |
2163 | * 21: DY2 22: DX2 | 2228 | * 21: DY2 22: DX2 |
2229 | * 23: DY3 24: DX3 | ||
2230 | * 25: DY4 26: DX4 | ||
2164 | */ | 2231 | */ |
2165 | 2232 | ||
2166 | /* Set the lane override configuration */ | 2233 | /* Set the lane override configuration */ |
2167 | 2234 | ||
2168 | /* REGLPTXSCPDAT4TO0DXDY */ | 2235 | /* REGLPTXSCPDAT4TO0DXDY */ |
2169 | REG_FLD_MOD(dsidev, DSI_DSIPHY_CFG10, l, 22, 17); | 2236 | REG_FLD_MOD(dsidev, DSI_DSIPHY_CFG10, l, lptxscp_start, 17); |
2170 | 2237 | ||
2171 | /* Enable lane override */ | 2238 | /* Enable lane override */ |
2172 | 2239 | ||
@@ -2248,6 +2315,7 @@ static int dsi_cio_init(struct omap_dss_device *dssdev) | |||
2248 | struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); | 2315 | struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); |
2249 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); | 2316 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); |
2250 | int r; | 2317 | int r; |
2318 | int num_data_lanes_dssdev = dsi_get_num_data_lanes_dssdev(dssdev); | ||
2251 | u32 l; | 2319 | u32 l; |
2252 | 2320 | ||
2253 | DSSDBGF(); | 2321 | DSSDBGF(); |
@@ -2279,6 +2347,8 @@ static int dsi_cio_init(struct omap_dss_device *dssdev) | |||
2279 | dsi_write_reg(dsidev, DSI_TIMING1, l); | 2347 | dsi_write_reg(dsidev, DSI_TIMING1, l); |
2280 | 2348 | ||
2281 | if (dsi->ulps_enabled) { | 2349 | if (dsi->ulps_enabled) { |
2350 | u32 lane_mask = DSI_CLK_P | DSI_DATA1_P | DSI_DATA2_P; | ||
2351 | |||
2282 | DSSDBG("manual ulps exit\n"); | 2352 | DSSDBG("manual ulps exit\n"); |
2283 | 2353 | ||
2284 | /* ULPS is exited by Mark-1 state for 1ms, followed by | 2354 | /* ULPS is exited by Mark-1 state for 1ms, followed by |
@@ -2289,8 +2359,13 @@ static int dsi_cio_init(struct omap_dss_device *dssdev) | |||
2289 | * manually. | 2359 | * manually. |
2290 | */ | 2360 | */ |
2291 | 2361 | ||
2292 | dsi_cio_enable_lane_override(dssdev, | 2362 | if (num_data_lanes_dssdev > 2) |
2293 | DSI_CLK_P | DSI_DATA1_P | DSI_DATA2_P); | 2363 | lane_mask |= DSI_DATA3_P; |
2364 | |||
2365 | if (num_data_lanes_dssdev > 3) | ||
2366 | lane_mask |= DSI_DATA4_P; | ||
2367 | |||
2368 | dsi_cio_enable_lane_override(dssdev, lane_mask); | ||
2294 | } | 2369 | } |
2295 | 2370 | ||
2296 | r = dsi_cio_power(dsidev, DSI_COMPLEXIO_POWER_ON); | 2371 | r = dsi_cio_power(dsidev, DSI_COMPLEXIO_POWER_ON); |
@@ -3495,12 +3570,7 @@ static void dsi_proto_timings(struct omap_dss_device *dssdev) | |||
3495 | /* min 60ns + 52*UI */ | 3570 | /* min 60ns + 52*UI */ |
3496 | tclk_post = ns2ddr(dsidev, 60) + 26; | 3571 | tclk_post = ns2ddr(dsidev, 60) + 26; |
3497 | 3572 | ||
3498 | /* ths_eot is 2 for 2 datalanes and 4 for 1 datalane */ | 3573 | ths_eot = DIV_ROUND_UP(4, dsi_get_num_data_lanes_dssdev(dssdev)); |
3499 | if (dssdev->phy.dsi.data1_lane != 0 && | ||
3500 | dssdev->phy.dsi.data2_lane != 0) | ||
3501 | ths_eot = 2; | ||
3502 | else | ||
3503 | ths_eot = 4; | ||
3504 | 3574 | ||
3505 | ddr_clk_pre = DIV_ROUND_UP(tclk_pre + tlpx + tclk_zero + tclk_prepare, | 3575 | ddr_clk_pre = DIV_ROUND_UP(tclk_pre + tlpx + tclk_zero + tclk_prepare, |
3506 | 4); | 3576 | 4); |
@@ -4220,6 +4290,7 @@ int dsi_init_display(struct omap_dss_device *dssdev) | |||
4220 | { | 4290 | { |
4221 | struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); | 4291 | struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); |
4222 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); | 4292 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); |
4293 | int dsi_module = dsi_get_dsidev_id(dsidev); | ||
4223 | 4294 | ||
4224 | DSSDBG("DSI init\n"); | 4295 | DSSDBG("DSI init\n"); |
4225 | 4296 | ||
@@ -4240,6 +4311,12 @@ int dsi_init_display(struct omap_dss_device *dssdev) | |||
4240 | dsi->vdds_dsi_reg = vdds_dsi; | 4311 | dsi->vdds_dsi_reg = vdds_dsi; |
4241 | } | 4312 | } |
4242 | 4313 | ||
4314 | if (dsi_get_num_data_lanes_dssdev(dssdev) > dsi->num_data_lanes) { | ||
4315 | DSSERR("DSI%d can't support more than %d data lanes\n", | ||
4316 | dsi_module + 1, dsi->num_data_lanes); | ||
4317 | return -EINVAL; | ||
4318 | } | ||
4319 | |||
4243 | return 0; | 4320 | return 0; |
4244 | } | 4321 | } |
4245 | 4322 | ||
@@ -4416,6 +4493,8 @@ static int dsi_init(struct platform_device *dsidev) | |||
4416 | dev_dbg(&dsidev->dev, "OMAP DSI rev %d.%d\n", | 4493 | dev_dbg(&dsidev->dev, "OMAP DSI rev %d.%d\n", |
4417 | FLD_GET(rev, 7, 4), FLD_GET(rev, 3, 0)); | 4494 | FLD_GET(rev, 7, 4), FLD_GET(rev, 3, 0)); |
4418 | 4495 | ||
4496 | dsi->num_data_lanes = dsi_get_num_data_lanes(dsidev); | ||
4497 | |||
4419 | enable_clocks(0); | 4498 | enable_clocks(0); |
4420 | 4499 | ||
4421 | return 0; | 4500 | return 0; |
diff --git a/drivers/video/omap2/dss/dss_features.c b/drivers/video/omap2/dss/dss_features.c index 5be5eb0f149..6460b0af335 100644 --- a/drivers/video/omap2/dss/dss_features.c +++ b/drivers/video/omap2/dss/dss_features.c | |||
@@ -294,7 +294,8 @@ static const struct omap_dss_features omap4_dss_features = { | |||
294 | FEAT_GLOBAL_ALPHA | FEAT_PRE_MULT_ALPHA | | 294 | FEAT_GLOBAL_ALPHA | FEAT_PRE_MULT_ALPHA | |
295 | FEAT_MGR_LCD2 | FEAT_GLOBAL_ALPHA_VID1 | | 295 | FEAT_MGR_LCD2 | FEAT_GLOBAL_ALPHA_VID1 | |
296 | FEAT_CORE_CLK_DIV | FEAT_LCD_CLK_SRC | | 296 | FEAT_CORE_CLK_DIV | FEAT_LCD_CLK_SRC | |
297 | FEAT_DSI_DCS_CMD_CONFIG_VC | FEAT_DSI_VC_OCP_WIDTH, | 297 | FEAT_DSI_DCS_CMD_CONFIG_VC | FEAT_DSI_VC_OCP_WIDTH | |
298 | FEAT_DSI_GNQ, | ||
298 | 299 | ||
299 | .num_mgrs = 3, | 300 | .num_mgrs = 3, |
300 | .num_ovls = 3, | 301 | .num_ovls = 3, |
diff --git a/drivers/video/omap2/dss/dss_features.h b/drivers/video/omap2/dss/dss_features.h index 857162b56f6..ff2cf33b07a 100644 --- a/drivers/video/omap2/dss/dss_features.h +++ b/drivers/video/omap2/dss/dss_features.h | |||
@@ -47,6 +47,7 @@ enum dss_feat_id { | |||
47 | FEAT_DSI_DCS_CMD_CONFIG_VC = 1 << 15, | 47 | FEAT_DSI_DCS_CMD_CONFIG_VC = 1 << 15, |
48 | FEAT_DSI_VC_OCP_WIDTH = 1 << 16, | 48 | FEAT_DSI_VC_OCP_WIDTH = 1 << 16, |
49 | FEAT_DSI_REVERSE_TXCLKESC = 1 << 17, | 49 | FEAT_DSI_REVERSE_TXCLKESC = 1 << 17, |
50 | FEAT_DSI_GNQ = 1 << 18, | ||
50 | }; | 51 | }; |
51 | 52 | ||
52 | /* DSS register field id */ | 53 | /* DSS register field id */ |