diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/video/omap2/dss/dsi.c | 83 |
1 files changed, 83 insertions, 0 deletions
diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c index 6a110b2bca4f..aea110c9d638 100644 --- a/drivers/video/omap2/dss/dsi.c +++ b/drivers/video/omap2/dss/dsi.c @@ -203,6 +203,21 @@ struct dsi_reg { u16 idx; }; typedef void (*omap_dsi_isr_t) (void *arg, u32 mask); #define DSI_MAX_NR_ISRS 2 +#define DSI_MAX_NR_LANES 5 + +enum dsi_lane_function { + DSI_LANE_UNUSED = 0, + DSI_LANE_CLK, + DSI_LANE_DATA1, + DSI_LANE_DATA2, + DSI_LANE_DATA3, + DSI_LANE_DATA4, +}; + +struct dsi_lane_config { + enum dsi_lane_function function; + u8 polarity; +}; struct dsi_isr_data { omap_dsi_isr_t isr; @@ -329,6 +344,9 @@ struct dsi_data { unsigned num_lanes_supported; + struct dsi_lane_config lanes[DSI_MAX_NR_LANES]; + unsigned num_lanes_used; + unsigned scp_clk_refcount; }; @@ -2077,6 +2095,65 @@ static unsigned dsi_get_line_buf_size(struct platform_device *dsidev) } } +static int dsi_parse_lane_config(struct omap_dss_device *dssdev) +{ + struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); + struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); + u8 lanes[DSI_MAX_NR_LANES]; + u8 polarities[DSI_MAX_NR_LANES]; + int num_lanes, i; + + static const enum dsi_lane_function functions[] = { + DSI_LANE_CLK, + DSI_LANE_DATA1, + DSI_LANE_DATA2, + DSI_LANE_DATA3, + DSI_LANE_DATA4, + }; + + lanes[0] = dssdev->phy.dsi.clk_lane; + lanes[1] = dssdev->phy.dsi.data1_lane; + lanes[2] = dssdev->phy.dsi.data2_lane; + lanes[3] = dssdev->phy.dsi.data3_lane; + lanes[4] = dssdev->phy.dsi.data4_lane; + polarities[0] = dssdev->phy.dsi.clk_pol; + polarities[1] = dssdev->phy.dsi.data1_pol; + polarities[2] = dssdev->phy.dsi.data2_pol; + polarities[3] = dssdev->phy.dsi.data3_pol; + polarities[4] = dssdev->phy.dsi.data4_pol; + + num_lanes = 0; + + for (i = 0; i < dsi->num_lanes_supported; ++i) + dsi->lanes[i].function = DSI_LANE_UNUSED; + + for (i = 0; i < dsi->num_lanes_supported; ++i) { + int num; + + if (lanes[i] == DSI_LANE_UNUSED) + break; + + num = lanes[i] - 1; + + if (num >= dsi->num_lanes_supported) + return -EINVAL; + + if (dsi->lanes[num].function != DSI_LANE_UNUSED) + return -EINVAL; + + dsi->lanes[num].function = functions[i]; + dsi->lanes[num].polarity = polarities[i]; + num_lanes++; + } + + if (num_lanes < 2 || num_lanes > dsi->num_lanes_supported) + return -EINVAL; + + dsi->num_lanes_used = num_lanes; + + return 0; +} + static void dsi_set_lane_config(struct omap_dss_device *dssdev) { struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); @@ -4328,6 +4405,12 @@ static int dsi_display_init_dsi(struct omap_dss_device *dssdev) int dsi_module = dsi_get_dsidev_id(dsidev); int r; + r = dsi_parse_lane_config(dssdev); + if (r) { + DSSERR("illegal lane config"); + goto err0; + } + r = dsi_pll_init(dsidev, true, true); if (r) goto err0; |