Message ID | 1314701495-11247-11-git-send-email-archit@ti.com (mailing list archive) |
---|---|
State | New, archived |
Delegated to: | Tomi Valkeinen |
Headers | show |
On Tue, 2011-08-30 at 16:21 +0530, Archit Taneja wrote: > Add initial support for DSI video mode panels: > - Add a new structure omap_dss_dsi_videomode_data in the member "panel" in > omap_dss_device struct. This allows panel driver to configure dsi video_mode > specific parameters. > - Configure basic DSI video mode timing parameters: HBP, HFP, HSA, VBP, VFP, VSA, > TL and VACT. > - Configure DSI protocol engine registers for video_mode support. > - Introduce functions dsi_video_mode_enable() and dsi_video_mode_disable() which > enable/disable video mode for a given virtual channel and a given pixel format > type. > > Things left for later > - Add functions to check for errors in video mode timings provided by panel. > - Configure timing registers required for command mode interleaving. > > Signed-off-by: Archit Taneja <archit@ti.com> > --- > drivers/video/omap2/dss/dsi.c | 256 ++++++++++++++++++++++++++++++++++++----- > include/video/omapdss.h | 32 +++++ > 2 files changed, 259 insertions(+), 29 deletions(-) > > diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c > index 582ae7b..e3d5c38 100644 > --- a/drivers/video/omap2/dss/dsi.c > +++ b/drivers/video/omap2/dss/dsi.c > @@ -132,7 +132,7 @@ struct dsi_reg { u16 idx; }; > #define DSI_IRQ_TA_TIMEOUT (1 << 20) > #define DSI_IRQ_ERROR_MASK \ > (DSI_IRQ_HS_TX_TIMEOUT | DSI_IRQ_LP_RX_TIMEOUT | DSI_IRQ_SYNC_LOST | \ > - DSI_IRQ_TA_TIMEOUT) > + DSI_IRQ_TA_TIMEOUT | DSI_IRQ_SYNC_LOST) > #define DSI_IRQ_CHANNEL_MASK 0xf > > /* Virtual channel interrupts */ > @@ -2472,6 +2472,12 @@ static int dsi_cio_init(struct omap_dss_device *dssdev) > > dsi_cio_timings(dsidev); > > + if (dssdev->panel.dsi_mode == OMAP_DSS_DSI_VIDEO_MODE) { > + /* DDR_CLK_ALWAYS_ON */ > + REG_FLD_MOD(dsidev, DSI_CLK_CTRL, > + dssdev->panel.dsi_vm_data.ddr_clk_always_on, 13, 13); > + } > + For the DDR clock to start, you need to send a null packet, don't you? Tomi -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Hi, On Thursday 01 September 2011 06:44 PM, Valkeinen, Tomi wrote: > On Tue, 2011-08-30 at 16:21 +0530, Archit Taneja wrote: >> Add initial support for DSI video mode panels: >> - Add a new structure omap_dss_dsi_videomode_data in the member "panel" in >> omap_dss_device struct. This allows panel driver to configure dsi video_mode >> specific parameters. >> - Configure basic DSI video mode timing parameters: HBP, HFP, HSA, VBP, VFP, VSA, >> TL and VACT. >> - Configure DSI protocol engine registers for video_mode support. >> - Introduce functions dsi_video_mode_enable() and dsi_video_mode_disable() which >> enable/disable video mode for a given virtual channel and a given pixel format >> type. >> >> Things left for later >> - Add functions to check for errors in video mode timings provided by panel. >> - Configure timing registers required for command mode interleaving. >> >> Signed-off-by: Archit Taneja<archit@ti.com> >> --- >> drivers/video/omap2/dss/dsi.c | 256 ++++++++++++++++++++++++++++++++++++----- >> include/video/omapdss.h | 32 +++++ >> 2 files changed, 259 insertions(+), 29 deletions(-) >> >> diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c >> index 582ae7b..e3d5c38 100644 >> --- a/drivers/video/omap2/dss/dsi.c >> +++ b/drivers/video/omap2/dss/dsi.c >> @@ -132,7 +132,7 @@ struct dsi_reg { u16 idx; }; >> #define DSI_IRQ_TA_TIMEOUT (1<< 20) >> #define DSI_IRQ_ERROR_MASK \ >> (DSI_IRQ_HS_TX_TIMEOUT | DSI_IRQ_LP_RX_TIMEOUT | DSI_IRQ_SYNC_LOST | \ >> - DSI_IRQ_TA_TIMEOUT) >> + DSI_IRQ_TA_TIMEOUT | DSI_IRQ_SYNC_LOST) >> #define DSI_IRQ_CHANNEL_MASK 0xf >> >> /* Virtual channel interrupts */ >> @@ -2472,6 +2472,12 @@ static int dsi_cio_init(struct omap_dss_device *dssdev) >> >> dsi_cio_timings(dsidev); >> >> + if (dssdev->panel.dsi_mode == OMAP_DSS_DSI_VIDEO_MODE) { >> + /* DDR_CLK_ALWAYS_ON */ >> + REG_FLD_MOD(dsidev, DSI_CLK_CTRL, >> + dssdev->panel.dsi_vm_data.ddr_clk_always_on, 13, 13); >> + } >> + > > For the DDR clock to start, you need to send a null packet, don't you? Yes, we have to send a null packet, but that is for the case when DDR clock is required by the panel to function properly. Hence we need to start the DDR clock right at the beginning(before we start sending DCS/generic commands to configure the panel). The panel driver may set DDR_CLK_ALWAYS_ON even if it has its own internal clock to function. In that case, we don't need it to be enabled right at the beginning, i.e, when we send DCS commands to configure the panel. In this case, the signal TxRequestHS will be asserted later on when we enable video mode for a VC, and that will start the DDR clock. I had left out the "sending null packet" part as I think its a more specific case. Setting DDR_CLK_ALWAYS_ON affects timing calculations, that is why I added it as a configurable parameter for the panel driver. Archit > > Tomi > > -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
On Fri, 2011-09-02 at 10:45 +0530, Archit Taneja wrote: > Hi, > > On Thursday 01 September 2011 06:44 PM, Valkeinen, Tomi wrote: > > On Tue, 2011-08-30 at 16:21 +0530, Archit Taneja wrote: > >> Add initial support for DSI video mode panels: > >> - Add a new structure omap_dss_dsi_videomode_data in the member "panel" in > >> omap_dss_device struct. This allows panel driver to configure dsi video_mode > >> specific parameters. > >> - Configure basic DSI video mode timing parameters: HBP, HFP, HSA, VBP, VFP, VSA, > >> TL and VACT. > >> - Configure DSI protocol engine registers for video_mode support. > >> - Introduce functions dsi_video_mode_enable() and dsi_video_mode_disable() which > >> enable/disable video mode for a given virtual channel and a given pixel format > >> type. > >> > >> Things left for later > >> - Add functions to check for errors in video mode timings provided by panel. > >> - Configure timing registers required for command mode interleaving. > >> > >> Signed-off-by: Archit Taneja<archit@ti.com> > >> --- > >> drivers/video/omap2/dss/dsi.c | 256 ++++++++++++++++++++++++++++++++++++----- > >> include/video/omapdss.h | 32 +++++ > >> 2 files changed, 259 insertions(+), 29 deletions(-) > >> > >> diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c > >> index 582ae7b..e3d5c38 100644 > >> --- a/drivers/video/omap2/dss/dsi.c > >> +++ b/drivers/video/omap2/dss/dsi.c > >> @@ -132,7 +132,7 @@ struct dsi_reg { u16 idx; }; > >> #define DSI_IRQ_TA_TIMEOUT (1<< 20) > >> #define DSI_IRQ_ERROR_MASK \ > >> (DSI_IRQ_HS_TX_TIMEOUT | DSI_IRQ_LP_RX_TIMEOUT | DSI_IRQ_SYNC_LOST | \ > >> - DSI_IRQ_TA_TIMEOUT) > >> + DSI_IRQ_TA_TIMEOUT | DSI_IRQ_SYNC_LOST) > >> #define DSI_IRQ_CHANNEL_MASK 0xf > >> > >> /* Virtual channel interrupts */ > >> @@ -2472,6 +2472,12 @@ static int dsi_cio_init(struct omap_dss_device *dssdev) > >> > >> dsi_cio_timings(dsidev); > >> > >> + if (dssdev->panel.dsi_mode == OMAP_DSS_DSI_VIDEO_MODE) { > >> + /* DDR_CLK_ALWAYS_ON */ > >> + REG_FLD_MOD(dsidev, DSI_CLK_CTRL, > >> + dssdev->panel.dsi_vm_data.ddr_clk_always_on, 13, 13); > >> + } > >> + > > > > For the DDR clock to start, you need to send a null packet, don't you? > > Yes, we have to send a null packet, but that is for the case when DDR > clock is required by the panel to function properly. Hence we need to > start the DDR clock right at the beginning(before we start sending > DCS/generic commands to configure the panel). > > The panel driver may set DDR_CLK_ALWAYS_ON even if it has its own > internal clock to function. In that case, we don't need it to be enabled > right at the beginning, i.e, when we send DCS commands to configure the > panel. In this case, the signal TxRequestHS will be asserted later on > when we enable video mode for a VC, and that will start the DDR clock. Why would the panel need DDR_CLK_ALWAYS_ON if it has an another fclk? I'm not that familiar with video mode, but somehow it would sound logical that if the panel wants DDR clock to be always on, it should be started right from the beginning. And if the panel doesn't need DDR clock to be always on, there's no need to even set DDR_CLK_ALWAYS_ON. > I had left out the "sending null packet" part as I think its a more > specific case. Setting DDR_CLK_ALWAYS_ON affects timing calculations, > that is why I added it as a configurable parameter for the panel driver. Ok. But your patches handle the calculations, don't they? Sending a null packet to start the DDR clk is rather OMAP specific internal thing, so I don't want to require the panel driver to need to know that it must send a null packet to start the clock. So if the ddr clk is not started automatically, I think we should have a function to do that (dsi_start_ddr_clk or whatever), which will then send the null packet (and perhaps return an error if DDR_CLK_ALWAYS_ON is not set, dunno...). Tomi -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
On Friday 02 September 2011 11:02 AM, Valkeinen, Tomi wrote: > On Fri, 2011-09-02 at 10:45 +0530, Archit Taneja wrote: >> Hi, >> >> On Thursday 01 September 2011 06:44 PM, Valkeinen, Tomi wrote: >>> On Tue, 2011-08-30 at 16:21 +0530, Archit Taneja wrote: >>>> Add initial support for DSI video mode panels: >>>> - Add a new structure omap_dss_dsi_videomode_data in the member "panel" in >>>> omap_dss_device struct. This allows panel driver to configure dsi video_mode >>>> specific parameters. >>>> - Configure basic DSI video mode timing parameters: HBP, HFP, HSA, VBP, VFP, VSA, >>>> TL and VACT. >>>> - Configure DSI protocol engine registers for video_mode support. >>>> - Introduce functions dsi_video_mode_enable() and dsi_video_mode_disable() which >>>> enable/disable video mode for a given virtual channel and a given pixel format >>>> type. >>>> >>>> Things left for later >>>> - Add functions to check for errors in video mode timings provided by panel. >>>> - Configure timing registers required for command mode interleaving. >>>> >>>> Signed-off-by: Archit Taneja<archit@ti.com> >>>> --- >>>> drivers/video/omap2/dss/dsi.c | 256 ++++++++++++++++++++++++++++++++++++----- >>>> include/video/omapdss.h | 32 +++++ >>>> 2 files changed, 259 insertions(+), 29 deletions(-) >>>> >>>> diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c >>>> index 582ae7b..e3d5c38 100644 >>>> --- a/drivers/video/omap2/dss/dsi.c >>>> +++ b/drivers/video/omap2/dss/dsi.c >>>> @@ -132,7 +132,7 @@ struct dsi_reg { u16 idx; }; >>>> #define DSI_IRQ_TA_TIMEOUT (1<< 20) >>>> #define DSI_IRQ_ERROR_MASK \ >>>> (DSI_IRQ_HS_TX_TIMEOUT | DSI_IRQ_LP_RX_TIMEOUT | DSI_IRQ_SYNC_LOST | \ >>>> - DSI_IRQ_TA_TIMEOUT) >>>> + DSI_IRQ_TA_TIMEOUT | DSI_IRQ_SYNC_LOST) >>>> #define DSI_IRQ_CHANNEL_MASK 0xf >>>> >>>> /* Virtual channel interrupts */ >>>> @@ -2472,6 +2472,12 @@ static int dsi_cio_init(struct omap_dss_device *dssdev) >>>> >>>> dsi_cio_timings(dsidev); >>>> >>>> + if (dssdev->panel.dsi_mode == OMAP_DSS_DSI_VIDEO_MODE) { >>>> + /* DDR_CLK_ALWAYS_ON */ >>>> + REG_FLD_MOD(dsidev, DSI_CLK_CTRL, >>>> + dssdev->panel.dsi_vm_data.ddr_clk_always_on, 13, 13); >>>> + } >>>> + >>> >>> For the DDR clock to start, you need to send a null packet, don't you? >> >> Yes, we have to send a null packet, but that is for the case when DDR >> clock is required by the panel to function properly. Hence we need to >> start the DDR clock right at the beginning(before we start sending >> DCS/generic commands to configure the panel). >> >> The panel driver may set DDR_CLK_ALWAYS_ON even if it has its own >> internal clock to function. In that case, we don't need it to be enabled >> right at the beginning, i.e, when we send DCS commands to configure the >> panel. In this case, the signal TxRequestHS will be asserted later on >> when we enable video mode for a VC, and that will start the DDR clock. > > Why would the panel need DDR_CLK_ALWAYS_ON if it has an another fclk? > I'm not that familiar with video mode, but somehow it would sound > logical that if the panel wants DDR clock to be always on, it should be > started right from the beginning. And if the panel doesn't need DDR > clock to be always on, there's no need to even set DDR_CLK_ALWAYS_ON. I'm not totally sure about this to be honest, but I have seen a customer panel which works on its internal clocks, but they may get disabled in certain scenarios, and at that point might need the host's HS clock. I'll try to find out more about this, I'm not totally clear about it myself. > >> I had left out the "sending null packet" part as I think its a more >> specific case. Setting DDR_CLK_ALWAYS_ON affects timing calculations, >> that is why I added it as a configurable parameter for the panel driver. > > Ok. But your patches handle the calculations, don't they? Well, not really. DDR_CLK_ALWAYS_ON being set/not set is used in the calculation of the final PLL divider values, and the horizontal/vertical timings for DISPC and DSI. Since these are all already provided by the panel driver, we don't need to do any calculations. I was considering to create a check_video_mode_timings function for later. That would validate if the timings calculated are correct with DDR_CLK_ALWAYS_ON set. > > Sending a null packet to start the DDR clk is rather OMAP specific > internal thing, so I don't want to require the panel driver to need to > know that it must send a null packet to start the clock. So if the ddr > clk is not started automatically, I think we should have a function to > do that (dsi_start_ddr_clk or whatever), which will then send the null > packet (and perhaps return an error if DDR_CLK_ALWAYS_ON is not set, > dunno...). Okay, If we can confirm that a panel asks for DDR_CLK_ALWAYS_ON mainly because it doesn't have its own fclk, then the dsi driver surely needs to start the DDR clock by sending a NULL packet. If this is to be done, one thing that has to be thought of is: - We need one of the requested VC's to be in HS mode for this. Do we enable HS for a VC in the dsi driver itself? Currently, its the job of the panel driver to enable HSmode for a VC. Is this a clean approach? Archit -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
On Fri, 2011-09-02 at 11:43 +0530, Archit Taneja wrote: > > Sending a null packet to start the DDR clk is rather OMAP specific > > internal thing, so I don't want to require the panel driver to need > to > > know that it must send a null packet to start the clock. So if the > ddr > > clk is not started automatically, I think we should have a function > to > > do that (dsi_start_ddr_clk or whatever), which will then send the > null > > packet (and perhaps return an error if DDR_CLK_ALWAYS_ON is not set, > > dunno...). > > Okay, If we can confirm that a panel asks for DDR_CLK_ALWAYS_ON > mainly > because it doesn't have its own fclk, then the dsi driver surely > needs > to start the DDR clock by sending a NULL packet. > > If this is to be done, one thing that has to be thought of is: > > - We need one of the requested VC's to be in HS mode for this. Do we > enable HS for a VC in the dsi driver itself? Currently, its the job > of > the panel driver to enable HSmode for a VC. Is this a clean approach? I have to say I don't have any idea what would be the best approach... What comes to my mind is that the DSI driver could automatically send the null packet, when: a) ddr_clk_always_on is set b) a channel is changed to HS and enabled (I guess it needs to be enabled also, does it?) Well, we do seem to enable all VCs at init phase (which, thinking about it, sounds a bit odd), so in practice we would just need to handle the omapdss_dsi_vc_enable_hs() case. Tomi -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
On Friday 02 September 2011 01:25 PM, Valkeinen, Tomi wrote: > On Fri, 2011-09-02 at 11:43 +0530, Archit Taneja wrote: >>> Sending a null packet to start the DDR clk is rather OMAP specific >>> internal thing, so I don't want to require the panel driver to need >> to >>> know that it must send a null packet to start the clock. So if the >> ddr >>> clk is not started automatically, I think we should have a function >> to >>> do that (dsi_start_ddr_clk or whatever), which will then send the >> null >>> packet (and perhaps return an error if DDR_CLK_ALWAYS_ON is not set, >>> dunno...). >> >> Okay, If we can confirm that a panel asks for DDR_CLK_ALWAYS_ON >> mainly >> because it doesn't have its own fclk, then the dsi driver surely >> needs >> to start the DDR clock by sending a NULL packet. >> >> If this is to be done, one thing that has to be thought of is: >> >> - We need one of the requested VC's to be in HS mode for this. Do we >> enable HS for a VC in the dsi driver itself? Currently, its the job >> of >> the panel driver to enable HSmode for a VC. Is this a clean approach? > > I have to say I don't have any idea what would be the best approach... > > What comes to my mind is that the DSI driver could automatically send > the null packet, when: > > a) ddr_clk_always_on is set > b) a channel is changed to HS and enabled (I guess it needs to be > enabled also, does it?) This approach sounds fine. The only drawback is that we send a NULL packet each time we enable a high speed channel. So if a panel is using 2 VCs, and it wants high speed for both channels(for some reason), we will be sending a NULL packet unnecessarily. One observation was that the DDR clock has to be enabled only after the bridge chip is reset. Enabling HS, and sending a NULL packet before doing a hw reset of the bridge chip doesn't bring up the panel(that is a bit peculiar). So we can't do this within omapdss_dsi_display_enable(). Archit > > Well, we do seem to enable all VCs at init phase (which, thinking about > it, sounds a bit odd), so in practice we would just need to handle the > omapdss_dsi_vc_enable_hs() case. > > Tomi > > -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
On Mon, 2011-09-05 at 11:22 +0530, Archit Taneja wrote: > On Friday 02 September 2011 01:25 PM, Valkeinen, Tomi wrote: > > On Fri, 2011-09-02 at 11:43 +0530, Archit Taneja wrote: > >>> Sending a null packet to start the DDR clk is rather OMAP specific > >>> internal thing, so I don't want to require the panel driver to need > >> to > >>> know that it must send a null packet to start the clock. So if the > >> ddr > >>> clk is not started automatically, I think we should have a function > >> to > >>> do that (dsi_start_ddr_clk or whatever), which will then send the > >> null > >>> packet (and perhaps return an error if DDR_CLK_ALWAYS_ON is not set, > >>> dunno...). > >> > >> Okay, If we can confirm that a panel asks for DDR_CLK_ALWAYS_ON > >> mainly > >> because it doesn't have its own fclk, then the dsi driver surely > >> needs > >> to start the DDR clock by sending a NULL packet. > >> > >> If this is to be done, one thing that has to be thought of is: > >> > >> - We need one of the requested VC's to be in HS mode for this. Do we > >> enable HS for a VC in the dsi driver itself? Currently, its the job > >> of > >> the panel driver to enable HSmode for a VC. Is this a clean approach? > > > > I have to say I don't have any idea what would be the best approach... > > > > What comes to my mind is that the DSI driver could automatically send > > the null packet, when: > > > > a) ddr_clk_always_on is set > > b) a channel is changed to HS and enabled (I guess it needs to be > > enabled also, does it?) > > This approach sounds fine. The only drawback is that we send a NULL > packet each time we enable a high speed channel. So if a panel is using > 2 VCs, and it wants high speed for both channels(for some reason), we > will be sending a NULL packet unnecessarily. True. I don't see that doing any harm, though, so I guess it's ok. > One observation was that the DDR clock has to be enabled only after the > bridge chip is reset. Enabling HS, and sending a NULL packet before > doing a hw reset of the bridge chip doesn't bring up the panel(that is a > bit peculiar). So we can't do this within omapdss_dsi_display_enable(). Well that does sound strange. What happens there? Any errors? Commands still going through? Hmm, although... Well, I'm guessing, but if the HW reset for the chip causes the chip to pull down the DSI lanes, or something similar, it could cause errors in the OMAP side. But is that happening or something else? Tomi -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
On Monday 05 September 2011 12:22 PM, Valkeinen, Tomi wrote: > On Mon, 2011-09-05 at 11:22 +0530, Archit Taneja wrote: >> On Friday 02 September 2011 01:25 PM, Valkeinen, Tomi wrote: >>> On Fri, 2011-09-02 at 11:43 +0530, Archit Taneja wrote: >>>>> Sending a null packet to start the DDR clk is rather OMAP specific >>>>> internal thing, so I don't want to require the panel driver to need >>>> to >>>>> know that it must send a null packet to start the clock. So if the >>>> ddr >>>>> clk is not started automatically, I think we should have a function >>>> to >>>>> do that (dsi_start_ddr_clk or whatever), which will then send the >>>> null >>>>> packet (and perhaps return an error if DDR_CLK_ALWAYS_ON is not set, >>>>> dunno...). >>>> >>>> Okay, If we can confirm that a panel asks for DDR_CLK_ALWAYS_ON >>>> mainly >>>> because it doesn't have its own fclk, then the dsi driver surely >>>> needs >>>> to start the DDR clock by sending a NULL packet. >>>> >>>> If this is to be done, one thing that has to be thought of is: >>>> >>>> - We need one of the requested VC's to be in HS mode for this. Do we >>>> enable HS for a VC in the dsi driver itself? Currently, its the job >>>> of >>>> the panel driver to enable HSmode for a VC. Is this a clean approach? >>> >>> I have to say I don't have any idea what would be the best approach... >>> >>> What comes to my mind is that the DSI driver could automatically send >>> the null packet, when: >>> >>> a) ddr_clk_always_on is set >>> b) a channel is changed to HS and enabled (I guess it needs to be >>> enabled also, does it?) >> >> This approach sounds fine. The only drawback is that we send a NULL >> packet each time we enable a high speed channel. So if a panel is using >> 2 VCs, and it wants high speed for both channels(for some reason), we >> will be sending a NULL packet unnecessarily. > > True. I don't see that doing any harm, though, so I guess it's ok. > >> One observation was that the DDR clock has to be enabled only after the >> bridge chip is reset. Enabling HS, and sending a NULL packet before >> doing a hw reset of the bridge chip doesn't bring up the panel(that is a >> bit peculiar). So we can't do this within omapdss_dsi_display_enable(). > > Well that does sound strange. What happens there? Any errors? Commands > still going through? The commands go through from OMAP side, but we don't get BTA Acks. I get the following errors: [ 4.527069] omapdss DSI error: DSI error, irqstatus 100180 [ 4.532836] DSI IRQ: 0x100180: PLL_LOCK PLL_UNLOCK TA_TIMEOUT I am not sure why "PLL_UNLOCK" occurs, but TA_TIMEOUT would make sense if the bridge chip isn't working properly. Archit > > Hmm, although... Well, I'm guessing, but if the HW reset for the chip > causes the chip to pull down the DSI lanes, or something similar, it > could cause errors in the OMAP side. But is that happening or something > else? > > Tomi > > -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c index 582ae7b..e3d5c38 100644 --- a/drivers/video/omap2/dss/dsi.c +++ b/drivers/video/omap2/dss/dsi.c @@ -132,7 +132,7 @@ struct dsi_reg { u16 idx; }; #define DSI_IRQ_TA_TIMEOUT (1 << 20) #define DSI_IRQ_ERROR_MASK \ (DSI_IRQ_HS_TX_TIMEOUT | DSI_IRQ_LP_RX_TIMEOUT | DSI_IRQ_SYNC_LOST | \ - DSI_IRQ_TA_TIMEOUT) + DSI_IRQ_TA_TIMEOUT | DSI_IRQ_SYNC_LOST) #define DSI_IRQ_CHANNEL_MASK 0xf /* Virtual channel interrupts */ @@ -2472,6 +2472,12 @@ static int dsi_cio_init(struct omap_dss_device *dssdev) dsi_cio_timings(dsidev); + if (dssdev->panel.dsi_mode == OMAP_DSS_DSI_VIDEO_MODE) { + /* DDR_CLK_ALWAYS_ON */ + REG_FLD_MOD(dsidev, DSI_CLK_CTRL, + dssdev->panel.dsi_vm_data.ddr_clk_always_on, 13, 13); + } + dsi->ulps_enabled = false; DSSDBG("CIO init done\n"); @@ -2496,6 +2502,9 @@ static void dsi_cio_uninit(struct omap_dss_device *dssdev) struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); + /* DDR_CLK_ALWAYS_ON */ + REG_FLD_MOD(dsidev, DSI_CLK_CTRL, 0, 13, 13); + dsi_cio_power(dsidev, DSI_COMPLEXIO_POWER_OFF); dsi_disable_scp_clk(dsidev); dsi->disable_pads(dsidev->id, dsi_get_lane_mask(dssdev)); @@ -3683,6 +3692,75 @@ static void dsi_set_hs_tx_timeout(struct platform_device *dsidev, ticks, x4 ? " x4" : "", x16 ? " x16" : "", (total_ticks * 1000) / (fck / 1000 / 1000)); } + +static void dsi_config_vp_num_line_buffers(struct omap_dss_device *dssdev) +{ + struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); + int num_line_buffers; + + if (dssdev->panel.dsi_mode == OMAP_DSS_DSI_VIDEO_MODE) { + int bpp = dsi_get_pixel_size(dssdev->panel.dsi_pix_fmt); + unsigned line_buf_size = dsi_get_line_buf_size(dsidev); + struct omap_video_timings *timings = &dssdev->panel.timings; + /* + * Don't use line buffers if width is greater than the video + * port's line buffer size + */ + if (line_buf_size <= timings->x_res * bpp / 8) + num_line_buffers = 0; + else + num_line_buffers = 2; + } else { + /* Use maximum number of line buffers in command mode */ + num_line_buffers = 2; + } + + /* LINE_BUFFER */ + REG_FLD_MOD(dsidev, DSI_CTRL, num_line_buffers, 13, 12); +} + +static void dsi_config_vp_sync_events(struct omap_dss_device *dssdev) +{ + struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); + int de_pol = dssdev->panel.dsi_vm_data.vp_de_pol; + int hsync_pol = dssdev->panel.dsi_vm_data.vp_hsync_pol; + int vsync_pol = dssdev->panel.dsi_vm_data.vp_vsync_pol; + bool vsync_end = dssdev->panel.dsi_vm_data.vp_vsync_end; + bool hsync_end = dssdev->panel.dsi_vm_data.vp_hsync_end; + u32 r; + + r = dsi_read_reg(dsidev, DSI_CTRL); + r = FLD_MOD(r, de_pol, 9, 9); /* VP_DE_POL */ + r = FLD_MOD(r, hsync_pol, 10, 10); /* VP_HSYNC_POL */ + r = FLD_MOD(r, vsync_pol, 11, 11); /* VP_VSYNC_POL */ + r = FLD_MOD(r, 1, 15, 15); /* VP_VSYNC_START */ + r = FLD_MOD(r, vsync_end, 16, 16); /* VP_VSYNC_END */ + r = FLD_MOD(r, 1, 17, 17); /* VP_HSYNC_START */ + r = FLD_MOD(r, hsync_end, 18, 18); /* VP_HSYNC_END */ + dsi_write_reg(dsidev, DSI_CTRL, r); +} + +static void dsi_config_blanking_modes(struct omap_dss_device *dssdev) +{ + struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); + int blanking_mode = dssdev->panel.dsi_vm_data.blanking_mode; + int hfp_blanking_mode = dssdev->panel.dsi_vm_data.hfp_blanking_mode; + int hbp_blanking_mode = dssdev->panel.dsi_vm_data.hbp_blanking_mode; + int hsa_blanking_mode = dssdev->panel.dsi_vm_data.hsa_blanking_mode; + u32 r; + + /* + * 0 = TX FIFO packets sent or LPS in corresponding blanking periods + * 1 = Long blanking packets are sent in corresponding blanking periods + */ + r = dsi_read_reg(dsidev, DSI_CTRL); + r = FLD_MOD(r, blanking_mode, 20, 20); /* BLANKING_MODE */ + r = FLD_MOD(r, hfp_blanking_mode, 21, 21); /* HFP_BLANKING */ + r = FLD_MOD(r, hbp_blanking_mode, 22, 22); /* HBP_BLANKING */ + r = FLD_MOD(r, hsa_blanking_mode, 23, 23); /* HSA_BLANKING */ + dsi_write_reg(dsidev, DSI_CTRL, r); +} + static int dsi_proto_config(struct omap_dss_device *dssdev) { struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); @@ -3726,7 +3804,6 @@ static int dsi_proto_config(struct omap_dss_device *dssdev) r = FLD_MOD(r, 1, 4, 4); /* VP_CLK_RATIO, always 1, see errata*/ r = FLD_MOD(r, buswidth, 7, 6); /* VP_DATA_BUS_WIDTH */ r = FLD_MOD(r, 0, 8, 8); /* VP_CLK_POL */ - r = FLD_MOD(r, 2, 13, 12); /* LINE_BUFFER, 2 lines */ r = FLD_MOD(r, 1, 14, 14); /* TRIGGER_RESET_MODE */ r = FLD_MOD(r, 1, 19, 19); /* EOT_ENABLE */ if (!dss_has_feature(FEAT_DSI_DCS_CMD_CONFIG_VC)) { @@ -3737,6 +3814,13 @@ static int dsi_proto_config(struct omap_dss_device *dssdev) dsi_write_reg(dsidev, DSI_CTRL, r); + dsi_config_vp_num_line_buffers(dssdev); + + if (dssdev->panel.dsi_mode == OMAP_DSS_DSI_VIDEO_MODE) { + dsi_config_vp_sync_events(dssdev); + dsi_config_blanking_modes(dssdev); + } + dsi_vc_initial_config(dsidev, 0); dsi_vc_initial_config(dsidev, 1); dsi_vc_initial_config(dsidev, 2); @@ -3755,6 +3839,7 @@ static void dsi_proto_timings(struct omap_dss_device *dssdev) unsigned ddr_clk_pre, ddr_clk_post; unsigned enter_hs_mode_lat, exit_hs_mode_lat; unsigned ths_eot; + int ndl = dsi_get_num_data_lanes_dssdev(dssdev); u32 r; r = dsi_read_reg(dsidev, DSI_DSIPHY_CFG0); @@ -3777,7 +3862,7 @@ static void dsi_proto_timings(struct omap_dss_device *dssdev) /* min 60ns + 52*UI */ tclk_post = ns2ddr(dsidev, 60) + 26; - ths_eot = DIV_ROUND_UP(4, dsi_get_num_data_lanes_dssdev(dssdev)); + ths_eot = DIV_ROUND_UP(4, ndl); ddr_clk_pre = DIV_ROUND_UP(tclk_pre + tlpx + tclk_zero + tclk_prepare, 4); @@ -3807,8 +3892,115 @@ static void dsi_proto_timings(struct omap_dss_device *dssdev) DSSDBG("enter_hs_mode_lat %u, exit_hs_mode_lat %u\n", enter_hs_mode_lat, exit_hs_mode_lat); + + if (dssdev->panel.dsi_mode == OMAP_DSS_DSI_VIDEO_MODE) { + /* TODO: Implement a video mode check_timings function */ + int hsa = dssdev->panel.dsi_vm_data.hsa; + int hfp = dssdev->panel.dsi_vm_data.hfp; + int hbp = dssdev->panel.dsi_vm_data.hbp; + int vsa = dssdev->panel.dsi_vm_data.vsa; + int vfp = dssdev->panel.dsi_vm_data.vfp; + int vbp = dssdev->panel.dsi_vm_data.vbp; + int window_sync = dssdev->panel.dsi_vm_data.window_sync; + bool hsync_end = dssdev->panel.dsi_vm_data.vp_hsync_end; + struct omap_video_timings *timings = &dssdev->panel.timings; + int bpp = dsi_get_pixel_size(dssdev->panel.dsi_pix_fmt); + int tl, t_he, width_bytes; + + t_he = hsync_end ? + ((hsa == 0 && ndl == 3) ? 1 : DIV_ROUND_UP(4, ndl)) : 0; + + width_bytes = DIV_ROUND_UP(timings->x_res * bpp, 8); + + /* TL = t_HS + HSA + t_HE + HFP + ceil((WC + 6) / NDL) + HBP */ + tl = DIV_ROUND_UP(4, ndl) + (hsync_end ? hsa : 0) + t_he + hfp + + DIV_ROUND_UP(width_bytes + 6, ndl) + hbp; + + DSSDBG("HBP: %d, HFP: %d, HSA: %d, TL: %d TXBYTECLKHS\n", hbp, + hfp, hsync_end ? hsa : 0, tl); + DSSDBG("VBP: %d, VFP: %d, VSA: %d, VACT: %d lines\n", vbp, vfp, + vsa, timings->y_res); + + r = dsi_read_reg(dsidev, DSI_VM_TIMING1); + r = FLD_MOD(r, hbp, 11, 0); /* HBP */ + r = FLD_MOD(r, hfp, 23, 12); /* HFP */ + r = FLD_MOD(r, hsync_end ? hsa : 0, 31, 24); /* HSA */ + dsi_write_reg(dsidev, DSI_VM_TIMING1, r); + + r = dsi_read_reg(dsidev, DSI_VM_TIMING2); + r = FLD_MOD(r, vbp, 7, 0); /* VBP */ + r = FLD_MOD(r, vfp, 15, 8); /* VFP */ + r = FLD_MOD(r, vsa, 23, 16); /* VSA */ + r = FLD_MOD(r, window_sync, 27, 24); /* WINDOW_SYNC */ + dsi_write_reg(dsidev, DSI_VM_TIMING2, r); + + r = dsi_read_reg(dsidev, DSI_VM_TIMING3); + r = FLD_MOD(r, timings->y_res, 14, 0); /* VACT */ + r = FLD_MOD(r, tl, 31, 16); /* TL */ + dsi_write_reg(dsidev, DSI_VM_TIMING3, r); + } } +int dsi_video_mode_enable(struct omap_dss_device *dssdev, int channel) +{ + struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); + int bpp = dsi_get_pixel_size(dssdev->panel.dsi_pix_fmt); + u8 data_type; + u16 word_count; + + switch (dssdev->panel.dsi_pix_fmt) { + case OMAP_DSS_DSI_FMT_RGB888: + data_type = MIPI_DSI_PACKED_PIXEL_STREAM_24; + break; + case OMAP_DSS_DSI_FMT_RGB666: + data_type = MIPI_DSI_PIXEL_STREAM_3BYTE_18; + break; + case OMAP_DSS_DSI_FMT_RGB666_PACKED: + data_type = MIPI_DSI_PACKED_PIXEL_STREAM_18; + break; + case OMAP_DSS_DSI_FMT_RGB565: + data_type = MIPI_DSI_PACKED_PIXEL_STREAM_16; + break; + default: + BUG(); + }; + + dsi_if_enable(dsidev, false); + dsi_vc_enable(dsidev, channel, false); + + /* MODE, 1 = video mode */ + REG_FLD_MOD(dsidev, DSI_VC_CTRL(channel), 1, 4, 4); + + word_count = DIV_ROUND_UP(dssdev->panel.timings.x_res * bpp, 8); + + dsi_vc_write_long_header(dsidev, channel, data_type, word_count, 0); + + dsi_vc_enable(dsidev, channel, true); + dsi_if_enable(dsidev, true); + + dssdev->manager->enable(dssdev->manager); + + return 0; +} +EXPORT_SYMBOL(dsi_video_mode_enable); + +void dsi_video_mode_disable(struct omap_dss_device *dssdev, int channel) +{ + struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); + + dsi_if_enable(dsidev, false); + dsi_vc_enable(dsidev, channel, false); + + /* MODE, 0 = command mode */ + REG_FLD_MOD(dsidev, DSI_VC_CTRL(channel), 0, 4, 4); + + dsi_vc_enable(dsidev, channel, true); + dsi_if_enable(dsidev, true); + + dssdev->manager->disable(dssdev->manager); +} +EXPORT_SYMBOL(dsi_video_mode_disable); + static void dsi_update_screen_dispc(struct omap_dss_device *dssdev, u16 x, u16 y, u16 w, u16 h) { @@ -4020,28 +4212,9 @@ EXPORT_SYMBOL(omap_dsi_update); static int dsi_display_init_dispc(struct omap_dss_device *dssdev) { int r; - u32 irq; - - irq = dssdev->manager->id == OMAP_DSS_CHANNEL_LCD ? - DISPC_IRQ_FRAMEDONE : DISPC_IRQ_FRAMEDONE2; - - r = omap_dispc_register_isr(dsi_framedone_irq_callback, (void *) dssdev, - irq); - if (r) { - DSSERR("can't get FRAMEDONE irq\n"); - return r; - } - - dispc_mgr_set_lcd_display_type(dssdev->manager->id, - OMAP_DSS_LCD_DISPLAY_TFT); - - dispc_mgr_enable_stallmode(dssdev->manager->id, true); - dispc_mgr_enable_fifohandcheck(dssdev->manager->id, 1); - - dispc_mgr_set_tft_data_lines(dssdev->manager->id, - dsi_get_pixel_size(dssdev->panel.dsi_pix_fmt)); - { + if (dssdev->panel.dsi_mode == OMAP_DSS_DSI_CMD_MODE) { + u32 irq; struct omap_video_timings timings = { .hsw = 1, .hfp = 1, @@ -4051,21 +4224,46 @@ static int dsi_display_init_dispc(struct omap_dss_device *dssdev) .vbp = 0, }; + irq = dssdev->manager->id == OMAP_DSS_CHANNEL_LCD ? + DISPC_IRQ_FRAMEDONE : DISPC_IRQ_FRAMEDONE2; + + r = omap_dispc_register_isr(dsi_framedone_irq_callback, + (void *) dssdev, irq); + if (r) { + DSSERR("can't get FRAMEDONE irq\n"); + return r; + } + + dispc_mgr_enable_stallmode(dssdev->manager->id, true); + dispc_mgr_enable_fifohandcheck(dssdev->manager->id, 1); + dispc_mgr_set_lcd_timings(dssdev->manager->id, &timings); + } else { + dispc_mgr_enable_stallmode(dssdev->manager->id, false); + dispc_mgr_enable_fifohandcheck(dssdev->manager->id, 0); + + dispc_mgr_set_lcd_timings(dssdev->manager->id, + &dssdev->panel.timings); } + dispc_mgr_set_lcd_display_type(dssdev->manager->id, + OMAP_DSS_LCD_DISPLAY_TFT); + dispc_mgr_set_tft_data_lines(dssdev->manager->id, + dsi_get_pixel_size(dssdev->panel.dsi_pix_fmt)); return 0; } static void dsi_display_uninit_dispc(struct omap_dss_device *dssdev) { - u32 irq; + if (dssdev->panel.dsi_mode == OMAP_DSS_DSI_CMD_MODE) { + u32 irq; - irq = dssdev->manager->id == OMAP_DSS_CHANNEL_LCD ? - DISPC_IRQ_FRAMEDONE : DISPC_IRQ_FRAMEDONE2; + irq = dssdev->manager->id == OMAP_DSS_CHANNEL_LCD ? + DISPC_IRQ_FRAMEDONE : DISPC_IRQ_FRAMEDONE2; - omap_dispc_unregister_isr(dsi_framedone_irq_callback, (void *) dssdev, - irq); + omap_dispc_unregister_isr(dsi_framedone_irq_callback, + (void *) dssdev, irq); + } } static int dsi_configure_dsi_clocks(struct omap_dss_device *dssdev) diff --git a/include/video/omapdss.h b/include/video/omapdss.h index 1e9a35c..c462ed0 100644 --- a/include/video/omapdss.h +++ b/include/video/omapdss.h @@ -228,6 +228,35 @@ void rfbi_bus_lock(void); void rfbi_bus_unlock(void); /* DSI */ + +struct omap_dss_dsi_videomode_data { + /* DSI video mode blanking data */ + /* Unit: byte clock cycles */ + u16 hsa; + u16 hfp; + u16 hbp; + /* Unit: line clocks */ + u16 vsa; + u16 vfp; + u16 vbp; + + /* DSI blanking modes */ + int blanking_mode; + int hsa_blanking_mode; + int hbp_blanking_mode; + int hfp_blanking_mode; + + /* Video port sync events */ + int vp_de_pol; + int vp_hsync_pol; + int vp_vsync_pol; + bool vp_vsync_end; + bool vp_hsync_end; + + bool ddr_clk_always_on; + int window_sync; +}; + void dsi_bus_lock(struct omap_dss_device *dssdev); void dsi_bus_unlock(struct omap_dss_device *dssdev); int dsi_vc_dcs_write(struct omap_dss_device *dssdev, int channel, u8 *data, @@ -258,6 +287,8 @@ int dsi_vc_set_max_rx_packet_size(struct omap_dss_device *dssdev, int channel, u16 len); int dsi_vc_send_null(struct omap_dss_device *dssdev, int channel); int dsi_vc_send_bta_sync(struct omap_dss_device *dssdev, int channel); +int dsi_video_mode_enable(struct omap_dss_device *dssdev, int channel); +void dsi_video_mode_disable(struct omap_dss_device *dssdev, int channel); /* Board specific data */ struct omap_dss_board_info { @@ -498,6 +529,7 @@ struct omap_dss_device { enum omap_dss_dsi_pixel_format dsi_pix_fmt; enum omap_dss_dsi_mode dsi_mode; + struct omap_dss_dsi_videomode_data dsi_vm_data; } panel; struct {
Add initial support for DSI video mode panels: - Add a new structure omap_dss_dsi_videomode_data in the member "panel" in omap_dss_device struct. This allows panel driver to configure dsi video_mode specific parameters. - Configure basic DSI video mode timing parameters: HBP, HFP, HSA, VBP, VFP, VSA, TL and VACT. - Configure DSI protocol engine registers for video_mode support. - Introduce functions dsi_video_mode_enable() and dsi_video_mode_disable() which enable/disable video mode for a given virtual channel and a given pixel format type. Things left for later - Add functions to check for errors in video mode timings provided by panel. - Configure timing registers required for command mode interleaving. Signed-off-by: Archit Taneja <archit@ti.com> --- drivers/video/omap2/dss/dsi.c | 256 ++++++++++++++++++++++++++++++++++++----- include/video/omapdss.h | 32 +++++ 2 files changed, 259 insertions(+), 29 deletions(-)