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

Fix divide by zero and broken output. Commit 600ce1a0fa ("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: Mark 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: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

authored by Mark Brown and committed by Linus Torvalds eb29a5cc 7e660872

+8 -6
+8 -6
drivers/video/s3c-fb.c
··· 211 212 /** 213 * s3c_fb_calc_pixclk() - calculate the divider to create the pixel clock. 214 - * @id: window id. 215 * @sfb: The hardware state. 216 * @pixclock: The pixel clock wanted, in picoseconds. 217 * 218 * Given the specified pixel clock, work out the necessary divider to get 219 * close to the output frequency. 220 */ 221 - static int s3c_fb_calc_pixclk(unsigned char id, struct s3c_fb *sfb, unsigned int pixclk) 222 { 223 - struct s3c_fb_pd_win *win = sfb->pdata->win[id]; 224 unsigned long clk = clk_get_rate(sfb->bus_clk); 225 unsigned int result; 226 227 - pixclk *= win->win_mode.refresh; 228 - result = clk / pixclk; 229 230 dev_dbg(sfb->dev, "pixclk=%u, clk=%lu, div=%d (%lu)\n", 231 pixclk, clk, result, clk / result); ··· 303 /* use window 0 as the basis for the lcd output timings */ 304 305 if (win_no == 0) { 306 - clkdiv = s3c_fb_calc_pixclk(win_no, sfb, var->pixclock); 307 308 data = sfb->pdata->vidcon0; 309 data &= ~(VIDCON0_CLKVAL_F_MASK | VIDCON0_CLKDIR);
··· 211 212 /** 213 * s3c_fb_calc_pixclk() - calculate the divider to create the pixel clock. 214 * @sfb: The hardware state. 215 * @pixclock: The pixel clock wanted, in picoseconds. 216 * 217 * Given the specified pixel clock, work out the necessary divider to get 218 * close to the output frequency. 219 */ 220 + static int s3c_fb_calc_pixclk(struct s3c_fb *sfb, unsigned int pixclk) 221 { 222 unsigned long clk = clk_get_rate(sfb->bus_clk); 223 + unsigned long long tmp; 224 unsigned int result; 225 226 + tmp = (unsigned long long)clk; 227 + tmp *= pixclk; 228 + 229 + do_div(tmp, 1000000000UL); 230 + result = (unsigned int)tmp / 1000; 231 232 dev_dbg(sfb->dev, "pixclk=%u, clk=%lu, div=%d (%lu)\n", 233 pixclk, clk, result, clk / result); ··· 301 /* use window 0 as the basis for the lcd output timings */ 302 303 if (win_no == 0) { 304 + clkdiv = s3c_fb_calc_pixclk(sfb, var->pixclock); 305 306 data = sfb->pdata->vidcon0; 307 data &= ~(VIDCON0_CLKVAL_F_MASK | VIDCON0_CLKDIR);