Commit eb29a5cc authored by Mark Brown's avatar Mark Brown Committed by Linus Torvalds

revert "drivers/video/s3c-fb.c: fix clock setting for Samsung SoC Framebuffer"

Fix divide by zero and broken output.  Commit 600ce1a0 ("fix clock
setting for Samsung SoC Framebuffer") introduced a mandatory refresh
parameter to the platform data for the S3C framebuffer but did not
introduce any validation code, causing existing platforms (none of which
have refresh set) to divide by zero whenever the framebuffer is
configured, generating warnings and unusable output.

Ben Dooks noted several problems with the patch:

 - The platform data supplies the pixclk directly and should already
   have taken care of the refresh rate.
 - The addition of a window ID parameter doesn't help since only the
   root framebuffer can control the pixclk.
 - pixclk is specified in picoseconds (rather than Hz) as the patch
   assumed.

and suggests reverting the commit so do that.  Without fixing this no
mainline user of the driver will produce output.

[akpm@linux-foundation.org: don't revert the correct bit]
Signed-off-by: default avatarMark Brown <broonie@opensource.wolfsonmicro.com>
Cc: InKi Dae <inki.dae@samsung.com>
Cc: Kyungmin Park <kmpark@infradead.org>
Cc: Krzysztof Helt <krzysztof.h1@poczta.fm>
Cc: Marek Szyprowski <m.szyprowski@samsung.com>
Cc: Ben Dooks <ben-linux@fluff.org>
Cc: <stable@kernel.org>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent 7e660872
...@@ -211,21 +211,23 @@ static int s3c_fb_check_var(struct fb_var_screeninfo *var, ...@@ -211,21 +211,23 @@ static int s3c_fb_check_var(struct fb_var_screeninfo *var,
/** /**
* s3c_fb_calc_pixclk() - calculate the divider to create the pixel clock. * s3c_fb_calc_pixclk() - calculate the divider to create the pixel clock.
* @id: window id.
* @sfb: The hardware state. * @sfb: The hardware state.
* @pixclock: The pixel clock wanted, in picoseconds. * @pixclock: The pixel clock wanted, in picoseconds.
* *
* Given the specified pixel clock, work out the necessary divider to get * Given the specified pixel clock, work out the necessary divider to get
* close to the output frequency. * close to the output frequency.
*/ */
static int s3c_fb_calc_pixclk(unsigned char id, struct s3c_fb *sfb, unsigned int pixclk) static int s3c_fb_calc_pixclk(struct s3c_fb *sfb, unsigned int pixclk)
{ {
struct s3c_fb_pd_win *win = sfb->pdata->win[id];
unsigned long clk = clk_get_rate(sfb->bus_clk); unsigned long clk = clk_get_rate(sfb->bus_clk);
unsigned long long tmp;
unsigned int result; unsigned int result;
pixclk *= win->win_mode.refresh; tmp = (unsigned long long)clk;
result = clk / pixclk; tmp *= pixclk;
do_div(tmp, 1000000000UL);
result = (unsigned int)tmp / 1000;
dev_dbg(sfb->dev, "pixclk=%u, clk=%lu, div=%d (%lu)\n", dev_dbg(sfb->dev, "pixclk=%u, clk=%lu, div=%d (%lu)\n",
pixclk, clk, result, clk / result); pixclk, clk, result, clk / result);
...@@ -301,7 +303,7 @@ static int s3c_fb_set_par(struct fb_info *info) ...@@ -301,7 +303,7 @@ static int s3c_fb_set_par(struct fb_info *info)
/* use window 0 as the basis for the lcd output timings */ /* use window 0 as the basis for the lcd output timings */
if (win_no == 0) { if (win_no == 0) {
clkdiv = s3c_fb_calc_pixclk(win_no, sfb, var->pixclock); clkdiv = s3c_fb_calc_pixclk(sfb, var->pixclock);
data = sfb->pdata->vidcon0; data = sfb->pdata->vidcon0;
data &= ~(VIDCON0_CLKVAL_F_MASK | VIDCON0_CLKDIR); data &= ~(VIDCON0_CLKVAL_F_MASK | VIDCON0_CLKDIR);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment