• Home
  • Raw
  • Download

Lines Matching +full:layer +full:- +full:alpha +full:- +full:mode

1 // SPDX-License-Identifier: GPL-2.0-only
2 /* linux/drivers/video/s3c-fb.c
5 * Copyright 2008-2010 Simtec Electronics
15 #include <linux/dma-mapping.h>
31 * setting of the alpha-blending functions that each window has, so only
35 * output timings and as the control for the output power-down state.
38 /* note, the previous use of <mach/regs-fb.h> to get platform specific data
58 #define VALID_BPP(x) (1 << ((x) - 1))
67 * struct s3c_fb_variant - fb variant information
110 * @has_osd_alpha: Set if can change alpha transparency for a window.
115 * @valid_bpp: 1 bit per BPP setting to show valid bits-per-pixel.
130 * struct s3c_fb_driverdata - per-device type driver data for init time.
140 * struct s3c_fb_palette - palette information
144 * @a: Alpha bitfield.
154 * struct s3c_fb_win - per window private data for each framebuffer.
177 * struct s3c_fb_vsync - vsync information
187 * struct s3c_fb - overall hardware state of the hardware
200 * @vsync_info: VSYNC-related information (count, queues...)
222 * s3c_fb_validate_win_bpp - validate the bits-per-pixel for this mode.
228 return win->variant.valid_bpp & VALID_BPP(bpp); in s3c_fb_validate_win_bpp()
232 * s3c_fb_check_var() - framebuffer layer request to verify a given mode.
236 * Framebuffer layer call to verify the given information and allow us to
242 struct s3c_fb_win *win = info->par; in s3c_fb_check_var()
243 struct s3c_fb *sfb = win->parent; in s3c_fb_check_var()
245 dev_dbg(sfb->dev, "checking parameters\n"); in s3c_fb_check_var()
247 var->xres_virtual = max(var->xres_virtual, var->xres); in s3c_fb_check_var()
248 var->yres_virtual = max(var->yres_virtual, var->yres); in s3c_fb_check_var()
250 if (!s3c_fb_validate_win_bpp(win, var->bits_per_pixel)) { in s3c_fb_check_var()
251 dev_dbg(sfb->dev, "win %d: unsupported bpp %d\n", in s3c_fb_check_var()
252 win->index, var->bits_per_pixel); in s3c_fb_check_var()
253 return -EINVAL; in s3c_fb_check_var()
257 var->transp.offset = 0; in s3c_fb_check_var()
258 var->transp.length = 0; in s3c_fb_check_var()
260 switch (var->bits_per_pixel) { in s3c_fb_check_var()
265 if (sfb->variant.palette[win->index] != 0) { in s3c_fb_check_var()
266 /* non palletised, A:1,R:2,G:3,B:2 mode */ in s3c_fb_check_var()
267 var->red.offset = 5; in s3c_fb_check_var()
268 var->green.offset = 2; in s3c_fb_check_var()
269 var->blue.offset = 0; in s3c_fb_check_var()
270 var->red.length = 2; in s3c_fb_check_var()
271 var->green.length = 3; in s3c_fb_check_var()
272 var->blue.length = 2; in s3c_fb_check_var()
273 var->transp.offset = 7; in s3c_fb_check_var()
274 var->transp.length = 1; in s3c_fb_check_var()
276 var->red.offset = 0; in s3c_fb_check_var()
277 var->red.length = var->bits_per_pixel; in s3c_fb_check_var()
278 var->green = var->red; in s3c_fb_check_var()
279 var->blue = var->red; in s3c_fb_check_var()
284 /* 666 with one bit alpha/transparency */ in s3c_fb_check_var()
285 var->transp.offset = 18; in s3c_fb_check_var()
286 var->transp.length = 1; in s3c_fb_check_var()
289 var->bits_per_pixel = 32; in s3c_fb_check_var()
292 var->red.offset = 12; in s3c_fb_check_var()
293 var->green.offset = 6; in s3c_fb_check_var()
294 var->blue.offset = 0; in s3c_fb_check_var()
295 var->red.length = 6; in s3c_fb_check_var()
296 var->green.length = 6; in s3c_fb_check_var()
297 var->blue.length = 6; in s3c_fb_check_var()
302 var->red.offset = 11; in s3c_fb_check_var()
303 var->green.offset = 5; in s3c_fb_check_var()
304 var->blue.offset = 0; in s3c_fb_check_var()
305 var->red.length = 5; in s3c_fb_check_var()
306 var->green.length = 6; in s3c_fb_check_var()
307 var->blue.length = 5; in s3c_fb_check_var()
313 var->transp.length = var->bits_per_pixel - 24; in s3c_fb_check_var()
314 var->transp.offset = 24; in s3c_fb_check_var()
318 var->bits_per_pixel = 32; in s3c_fb_check_var()
319 var->red.offset = 16; in s3c_fb_check_var()
320 var->red.length = 8; in s3c_fb_check_var()
321 var->green.offset = 8; in s3c_fb_check_var()
322 var->green.length = 8; in s3c_fb_check_var()
323 var->blue.offset = 0; in s3c_fb_check_var()
324 var->blue.length = 8; in s3c_fb_check_var()
328 dev_err(sfb->dev, "invalid bpp\n"); in s3c_fb_check_var()
329 return -EINVAL; in s3c_fb_check_var()
332 dev_dbg(sfb->dev, "%s: verified parameters\n", __func__); in s3c_fb_check_var()
337 * s3c_fb_calc_pixclk() - calculate the divider to create the pixel clock.
350 if (sfb->variant.has_clksel) in s3c_fb_calc_pixclk()
351 clk = clk_get_rate(sfb->bus_clk); in s3c_fb_calc_pixclk()
353 clk = clk_get_rate(sfb->lcd_clk); in s3c_fb_calc_pixclk()
361 dev_dbg(sfb->dev, "pixclk=%u, clk=%lu, div=%d (%lu)\n", in s3c_fb_calc_pixclk()
368 * s3c_fb_align_word() - align pixel count to word boundary
387 * vidosd_set_size() - set OSD size for a window
394 struct s3c_fb *sfb = win->parent; in vidosd_set_size()
397 if (win->variant.osd_size_off) in vidosd_set_size()
398 writel(size, sfb->regs + OSD_BASE(win->index, sfb->variant) in vidosd_set_size()
399 + win->variant.osd_size_off); in vidosd_set_size()
403 * vidosd_set_alpha() - set alpha transparency for a window
406 * @alpha: alpha register value
408 static void vidosd_set_alpha(struct s3c_fb_win *win, u32 alpha) in vidosd_set_alpha() argument
410 struct s3c_fb *sfb = win->parent; in vidosd_set_alpha()
412 if (win->variant.has_osd_alpha) in vidosd_set_alpha()
413 writel(alpha, sfb->regs + VIDOSD_C(win->index, sfb->variant)); in vidosd_set_alpha()
417 * shadow_protect_win() - disable updating values from shadow registers at vsync
424 struct s3c_fb *sfb = win->parent; in shadow_protect_win()
428 if (sfb->variant.has_prtcon) { in shadow_protect_win()
429 writel(PRTCON_PROTECT, sfb->regs + PRTCON); in shadow_protect_win()
430 } else if (sfb->variant.has_shadowcon) { in shadow_protect_win()
431 reg = readl(sfb->regs + SHADOWCON); in shadow_protect_win()
432 writel(reg | SHADOWCON_WINx_PROTECT(win->index), in shadow_protect_win()
433 sfb->regs + SHADOWCON); in shadow_protect_win()
436 if (sfb->variant.has_prtcon) { in shadow_protect_win()
437 writel(0, sfb->regs + PRTCON); in shadow_protect_win()
438 } else if (sfb->variant.has_shadowcon) { in shadow_protect_win()
439 reg = readl(sfb->regs + SHADOWCON); in shadow_protect_win()
440 writel(reg & ~SHADOWCON_WINx_PROTECT(win->index), in shadow_protect_win()
441 sfb->regs + SHADOWCON); in shadow_protect_win()
447 * s3c_fb_enable() - Set the state of the main LCD output
453 u32 vidcon0 = readl(sfb->regs + VIDCON0); in s3c_fb_enable()
455 if (enable && !sfb->output_on) in s3c_fb_enable()
456 pm_runtime_get_sync(sfb->dev); in s3c_fb_enable()
471 writel(vidcon0, sfb->regs + VIDCON0); in s3c_fb_enable()
473 if (!enable && sfb->output_on) in s3c_fb_enable()
474 pm_runtime_put_sync(sfb->dev); in s3c_fb_enable()
476 sfb->output_on = enable; in s3c_fb_enable()
480 * s3c_fb_set_par() - framebuffer request to set new framebuffer state.
483 * Framebuffer layer request to set a new mode for the specified framebuffer
487 struct fb_var_screeninfo *var = &info->var; in s3c_fb_set_par()
488 struct s3c_fb_win *win = info->par; in s3c_fb_set_par()
489 struct s3c_fb *sfb = win->parent; in s3c_fb_set_par()
490 void __iomem *regs = sfb->regs; in s3c_fb_set_par()
492 int win_no = win->index; in s3c_fb_set_par()
493 u32 alpha = 0; in s3c_fb_set_par() local
497 dev_dbg(sfb->dev, "setting framebuffer parameters\n"); in s3c_fb_set_par()
499 pm_runtime_get_sync(sfb->dev); in s3c_fb_set_par()
503 switch (var->bits_per_pixel) { in s3c_fb_set_par()
508 info->fix.visual = FB_VISUAL_TRUECOLOR; in s3c_fb_set_par()
511 if (win->variant.palette_sz >= 256) in s3c_fb_set_par()
512 info->fix.visual = FB_VISUAL_PSEUDOCOLOR; in s3c_fb_set_par()
514 info->fix.visual = FB_VISUAL_TRUECOLOR; in s3c_fb_set_par()
517 info->fix.visual = FB_VISUAL_MONO01; in s3c_fb_set_par()
520 info->fix.visual = FB_VISUAL_PSEUDOCOLOR; in s3c_fb_set_par()
524 info->fix.line_length = (var->xres_virtual * var->bits_per_pixel) / 8; in s3c_fb_set_par()
526 info->fix.xpanstep = info->var.xres_virtual > info->var.xres ? 1 : 0; in s3c_fb_set_par()
527 info->fix.ypanstep = info->var.yres_virtual > info->var.yres ? 1 : 0; in s3c_fb_set_par()
532 if (!sfb->output_on) in s3c_fb_set_par()
540 writel(info->fix.smem_start, buf + sfb->variant.buf_start); in s3c_fb_set_par()
542 data = info->fix.smem_start + info->fix.line_length * var->yres; in s3c_fb_set_par()
543 writel(data, buf + sfb->variant.buf_end); in s3c_fb_set_par()
545 pagewidth = (var->xres * var->bits_per_pixel) >> 3; in s3c_fb_set_par()
546 data = VIDW_BUF_SIZE_OFFSET(info->fix.line_length - pagewidth) | in s3c_fb_set_par()
548 VIDW_BUF_SIZE_OFFSET_E(info->fix.line_length - pagewidth) | in s3c_fb_set_par()
550 writel(data, regs + sfb->variant.buf_size + (win_no * 4)); in s3c_fb_set_par()
556 writel(data, regs + VIDOSD_A(win_no, sfb->variant)); in s3c_fb_set_par()
558 data = VIDOSDxB_BOTRIGHT_X(s3c_fb_align_word(var->bits_per_pixel, in s3c_fb_set_par()
559 var->xres - 1)) | in s3c_fb_set_par()
560 VIDOSDxB_BOTRIGHT_Y(var->yres - 1) | in s3c_fb_set_par()
561 VIDOSDxB_BOTRIGHT_X_E(s3c_fb_align_word(var->bits_per_pixel, in s3c_fb_set_par()
562 var->xres - 1)) | in s3c_fb_set_par()
563 VIDOSDxB_BOTRIGHT_Y_E(var->yres - 1); in s3c_fb_set_par()
565 writel(data, regs + VIDOSD_B(win_no, sfb->variant)); in s3c_fb_set_par()
567 data = var->xres * var->yres; in s3c_fb_set_par()
569 alpha = VIDISD14C_ALPHA1_R(0xf) | in s3c_fb_set_par()
573 vidosd_set_alpha(win, alpha); in s3c_fb_set_par()
577 if (sfb->variant.has_shadowcon) { in s3c_fb_set_par()
578 data = readl(sfb->regs + SHADOWCON); in s3c_fb_set_par()
580 writel(data, sfb->regs + SHADOWCON); in s3c_fb_set_par()
584 sfb->enabled |= (1 << win->index); in s3c_fb_set_par()
586 /* note, since we have to round up the bits-per-pixel, we end up in s3c_fb_set_par()
588 * exactly which mode of operation is intended. */ in s3c_fb_set_par()
590 switch (var->bits_per_pixel) { in s3c_fb_set_par()
607 if (var->transp.length != 0) in s3c_fb_set_par()
615 if (var->transp.length != 0) in s3c_fb_set_par()
624 if (var->red.length == 6) { in s3c_fb_set_par()
625 if (var->transp.length != 0) in s3c_fb_set_par()
629 } else if (var->transp.length == 1) in s3c_fb_set_par()
632 else if ((var->transp.length == 4) || in s3c_fb_set_par()
633 (var->transp.length == 8)) in s3c_fb_set_par()
647 void __iomem *keycon = regs + sfb->variant.keycon; in s3c_fb_set_par()
655 keycon += (win_no - 1) * 8; in s3c_fb_set_par()
661 writel(data, regs + sfb->variant.wincon + (win_no * 4)); in s3c_fb_set_par()
662 writel(0x0, regs + sfb->variant.winmap + (win_no * 4)); in s3c_fb_set_par()
664 /* Set alpha value width */ in s3c_fb_set_par()
665 if (sfb->variant.has_blendcon) { in s3c_fb_set_par()
666 data = readl(sfb->regs + BLENDCON); in s3c_fb_set_par()
668 if (var->transp.length > 4) in s3c_fb_set_par()
672 writel(data, sfb->regs + BLENDCON); in s3c_fb_set_par()
677 pm_runtime_put_sync(sfb->dev); in s3c_fb_set_par()
683 * s3c_fb_update_palette() - set or schedule a palette update.
704 palreg = sfb->regs + sfb->variant.palette[win->index]; in s3c_fb_update_palette()
706 dev_dbg(sfb->dev, "%s: win %d, reg %d (%p): %08x\n", in s3c_fb_update_palette()
707 __func__, win->index, reg, palreg, value); in s3c_fb_update_palette()
709 win->palette_buffer[reg] = value; in s3c_fb_update_palette()
711 palcon = readl(sfb->regs + WPALCON); in s3c_fb_update_palette()
712 writel(palcon | WPALCON_PAL_UPDATE, sfb->regs + WPALCON); in s3c_fb_update_palette()
714 if (win->variant.palette_16bpp) in s3c_fb_update_palette()
719 writel(palcon, sfb->regs + WPALCON); in s3c_fb_update_palette()
726 chan >>= 16 - bf->length; in chan_to_field()
727 return chan << bf->offset; in chan_to_field()
731 * s3c_fb_setcolreg() - framebuffer layer request to change palette.
736 * @trans: The transparency (alpha) field for the palette data.
743 struct s3c_fb_win *win = info->par; in s3c_fb_setcolreg()
744 struct s3c_fb *sfb = win->parent; in s3c_fb_setcolreg()
747 dev_dbg(sfb->dev, "%s: win %d: %d => rgb=%d/%d/%d\n", in s3c_fb_setcolreg()
748 __func__, win->index, regno, red, green, blue); in s3c_fb_setcolreg()
750 pm_runtime_get_sync(sfb->dev); in s3c_fb_setcolreg()
752 switch (info->fix.visual) { in s3c_fb_setcolreg()
754 /* true-colour, use pseudo-palette */ in s3c_fb_setcolreg()
757 u32 *pal = info->pseudo_palette; in s3c_fb_setcolreg()
759 val = chan_to_field(red, &info->var.red); in s3c_fb_setcolreg()
760 val |= chan_to_field(green, &info->var.green); in s3c_fb_setcolreg()
761 val |= chan_to_field(blue, &info->var.blue); in s3c_fb_setcolreg()
768 if (regno < win->variant.palette_sz) { in s3c_fb_setcolreg()
769 val = chan_to_field(red, &win->palette.r); in s3c_fb_setcolreg()
770 val |= chan_to_field(green, &win->palette.g); in s3c_fb_setcolreg()
771 val |= chan_to_field(blue, &win->palette.b); in s3c_fb_setcolreg()
779 pm_runtime_put_sync(sfb->dev); in s3c_fb_setcolreg()
783 pm_runtime_put_sync(sfb->dev); in s3c_fb_setcolreg()
788 * s3c_fb_blank() - blank or unblank the given window
792 * Framebuffer layer request to change the power state.
796 struct s3c_fb_win *win = info->par; in s3c_fb_blank()
797 struct s3c_fb *sfb = win->parent; in s3c_fb_blank()
798 unsigned int index = win->index; in s3c_fb_blank()
800 u32 output_on = sfb->output_on; in s3c_fb_blank()
802 dev_dbg(sfb->dev, "blank mode %d\n", blank_mode); in s3c_fb_blank()
804 pm_runtime_get_sync(sfb->dev); in s3c_fb_blank()
806 wincon = readl(sfb->regs + sfb->variant.wincon + (index * 4)); in s3c_fb_blank()
811 sfb->enabled &= ~(1 << index); in s3c_fb_blank()
818 sfb->regs + sfb->variant.winmap + (index * 4)); in s3c_fb_blank()
824 writel(0x0, sfb->regs + sfb->variant.winmap + (index * 4)); in s3c_fb_blank()
827 sfb->enabled |= (1 << index); in s3c_fb_blank()
833 pm_runtime_put_sync(sfb->dev); in s3c_fb_blank()
838 writel(wincon, sfb->regs + sfb->variant.wincon + (index * 4)); in s3c_fb_blank()
845 s3c_fb_enable(sfb, sfb->enabled ? 1 : 0); in s3c_fb_blank()
848 pm_runtime_put_sync(sfb->dev); in s3c_fb_blank()
850 return output_on == sfb->output_on; in s3c_fb_blank()
854 * s3c_fb_pan_display() - Pan the display.
867 struct s3c_fb_win *win = info->par; in s3c_fb_pan_display()
868 struct s3c_fb *sfb = win->parent; in s3c_fb_pan_display()
869 void __iomem *buf = sfb->regs + win->index * 8; in s3c_fb_pan_display()
872 pm_runtime_get_sync(sfb->dev); in s3c_fb_pan_display()
875 start_boff = var->yoffset * info->fix.line_length; in s3c_fb_pan_display()
877 if (info->var.bits_per_pixel >= 8) { in s3c_fb_pan_display()
878 start_boff += var->xoffset * (info->var.bits_per_pixel >> 3); in s3c_fb_pan_display()
880 switch (info->var.bits_per_pixel) { in s3c_fb_pan_display()
882 start_boff += var->xoffset >> 1; in s3c_fb_pan_display()
885 start_boff += var->xoffset >> 2; in s3c_fb_pan_display()
888 start_boff += var->xoffset >> 3; in s3c_fb_pan_display()
891 dev_err(sfb->dev, "invalid bpp\n"); in s3c_fb_pan_display()
892 pm_runtime_put_sync(sfb->dev); in s3c_fb_pan_display()
893 return -EINVAL; in s3c_fb_pan_display()
897 end_boff = start_boff + info->var.yres * info->fix.line_length; in s3c_fb_pan_display()
899 /* Temporarily turn off per-vsync update from shadow registers until in s3c_fb_pan_display()
903 writel(info->fix.smem_start + start_boff, buf + sfb->variant.buf_start); in s3c_fb_pan_display()
904 writel(info->fix.smem_start + end_boff, buf + sfb->variant.buf_end); in s3c_fb_pan_display()
908 pm_runtime_put_sync(sfb->dev); in s3c_fb_pan_display()
913 * s3c_fb_enable_irq() - enable framebuffer interrupts
918 void __iomem *regs = sfb->regs; in s3c_fb_enable_irq()
921 if (!test_and_set_bit(S3C_FB_VSYNC_IRQ_EN, &sfb->irq_flags)) { in s3c_fb_enable_irq()
938 * s3c_fb_disable_irq() - disable framebuffer interrupts
943 void __iomem *regs = sfb->regs; in s3c_fb_disable_irq()
946 if (test_and_clear_bit(S3C_FB_VSYNC_IRQ_EN, &sfb->irq_flags)) { in s3c_fb_disable_irq()
960 void __iomem *regs = sfb->regs; in s3c_fb_irq()
963 spin_lock(&sfb->slock); in s3c_fb_irq()
972 sfb->vsync_info.count++; in s3c_fb_irq()
973 wake_up_interruptible(&sfb->vsync_info.wait); in s3c_fb_irq()
981 spin_unlock(&sfb->slock); in s3c_fb_irq()
986 * s3c_fb_wait_for_vsync() - sleep until next VSYNC interrupt or timeout
996 return -ENODEV; in s3c_fb_wait_for_vsync()
998 pm_runtime_get_sync(sfb->dev); in s3c_fb_wait_for_vsync()
1000 count = sfb->vsync_info.count; in s3c_fb_wait_for_vsync()
1002 ret = wait_event_interruptible_timeout(sfb->vsync_info.wait, in s3c_fb_wait_for_vsync()
1003 count != sfb->vsync_info.count, in s3c_fb_wait_for_vsync()
1006 pm_runtime_put_sync(sfb->dev); in s3c_fb_wait_for_vsync()
1009 return -ETIMEDOUT; in s3c_fb_wait_for_vsync()
1017 struct s3c_fb_win *win = info->par; in s3c_fb_ioctl()
1018 struct s3c_fb *sfb = win->parent; in s3c_fb_ioctl()
1025 ret = -EFAULT; in s3c_fb_ioctl()
1032 ret = -ENOTTY; in s3c_fb_ioctl()
1052 * s3c_fb_missing_pixclock() - calculates pixel clock
1053 * @mode: The video mode to change.
1057 static void s3c_fb_missing_pixclock(struct fb_videomode *mode) in s3c_fb_missing_pixclock() argument
1062 div = mode->left_margin + mode->hsync_len + mode->right_margin + in s3c_fb_missing_pixclock()
1063 mode->xres; in s3c_fb_missing_pixclock()
1064 div *= mode->upper_margin + mode->vsync_len + mode->lower_margin + in s3c_fb_missing_pixclock()
1065 mode->yres; in s3c_fb_missing_pixclock()
1066 div *= mode->refresh ? : 60; in s3c_fb_missing_pixclock()
1070 mode->pixclock = pixclk; in s3c_fb_missing_pixclock()
1074 * s3c_fb_alloc_memory() - allocate display memory for framebuffer window
1082 struct s3c_fb_pd_win *windata = win->windata; in s3c_fb_alloc_memory()
1084 struct fb_info *fbi = win->fbinfo; in s3c_fb_alloc_memory()
1087 dev_dbg(sfb->dev, "allocating memory for display\n"); in s3c_fb_alloc_memory()
1089 real_size = windata->xres * windata->yres; in s3c_fb_alloc_memory()
1090 virt_size = windata->virtual_x * windata->virtual_y; in s3c_fb_alloc_memory()
1092 dev_dbg(sfb->dev, "real_size=%u (%u.%u), virt_size=%u (%u.%u)\n", in s3c_fb_alloc_memory()
1093 real_size, windata->xres, windata->yres, in s3c_fb_alloc_memory()
1094 virt_size, windata->virtual_x, windata->virtual_y); in s3c_fb_alloc_memory()
1097 size *= (windata->max_bpp > 16) ? 32 : windata->max_bpp; in s3c_fb_alloc_memory()
1100 fbi->fix.smem_len = size; in s3c_fb_alloc_memory()
1103 dev_dbg(sfb->dev, "want %u bytes for window\n", size); in s3c_fb_alloc_memory()
1105 fbi->screen_buffer = dma_alloc_wc(sfb->dev, size, &map_dma, GFP_KERNEL); in s3c_fb_alloc_memory()
1106 if (!fbi->screen_buffer) in s3c_fb_alloc_memory()
1107 return -ENOMEM; in s3c_fb_alloc_memory()
1109 dev_dbg(sfb->dev, "mapped %x to %p\n", in s3c_fb_alloc_memory()
1110 (unsigned int)map_dma, fbi->screen_buffer); in s3c_fb_alloc_memory()
1112 memset(fbi->screen_buffer, 0x0, size); in s3c_fb_alloc_memory()
1113 fbi->fix.smem_start = map_dma; in s3c_fb_alloc_memory()
1119 * s3c_fb_free_memory() - free the display memory for the given window
1127 struct fb_info *fbi = win->fbinfo; in s3c_fb_free_memory()
1129 if (fbi->screen_buffer) in s3c_fb_free_memory()
1130 dma_free_wc(sfb->dev, PAGE_ALIGN(fbi->fix.smem_len), in s3c_fb_free_memory()
1131 fbi->screen_buffer, fbi->fix.smem_start); in s3c_fb_free_memory()
1135 * s3c_fb_release_win() - release resources for a framebuffer window.
1145 if (win->fbinfo) { in s3c_fb_release_win()
1146 if (sfb->variant.has_shadowcon) { in s3c_fb_release_win()
1147 data = readl(sfb->regs + SHADOWCON); in s3c_fb_release_win()
1148 data &= ~SHADOWCON_CHx_ENABLE(win->index); in s3c_fb_release_win()
1149 data &= ~SHADOWCON_CHx_LOCAL_ENABLE(win->index); in s3c_fb_release_win()
1150 writel(data, sfb->regs + SHADOWCON); in s3c_fb_release_win()
1152 unregister_framebuffer(win->fbinfo); in s3c_fb_release_win()
1153 if (win->fbinfo->cmap.len) in s3c_fb_release_win()
1154 fb_dealloc_cmap(&win->fbinfo->cmap); in s3c_fb_release_win()
1156 framebuffer_release(win->fbinfo); in s3c_fb_release_win()
1161 * s3c_fb_probe_win() - register an hardware window
1181 dev_dbg(sfb->dev, "probing window %d, variant %p\n", win_no, variant); in s3c_fb_probe_win()
1183 init_waitqueue_head(&sfb->vsync_info.wait); in s3c_fb_probe_win()
1185 palette_size = variant->palette_sz * 4; in s3c_fb_probe_win()
1188 palette_size * sizeof(u32), sfb->dev); in s3c_fb_probe_win()
1190 return -ENOMEM; in s3c_fb_probe_win()
1192 windata = sfb->pdata->win[win_no]; in s3c_fb_probe_win()
1193 initmode = *sfb->pdata->vtiming; in s3c_fb_probe_win()
1195 WARN_ON(windata->max_bpp == 0); in s3c_fb_probe_win()
1196 WARN_ON(windata->xres == 0); in s3c_fb_probe_win()
1197 WARN_ON(windata->yres == 0); in s3c_fb_probe_win()
1199 win = fbinfo->par; in s3c_fb_probe_win()
1201 var = &fbinfo->var; in s3c_fb_probe_win()
1202 win->variant = *variant; in s3c_fb_probe_win()
1203 win->fbinfo = fbinfo; in s3c_fb_probe_win()
1204 win->parent = sfb; in s3c_fb_probe_win()
1205 win->windata = windata; in s3c_fb_probe_win()
1206 win->index = win_no; in s3c_fb_probe_win()
1207 win->palette_buffer = (u32 *)(win + 1); in s3c_fb_probe_win()
1211 dev_err(sfb->dev, "failed to allocate display memory\n"); in s3c_fb_probe_win()
1216 if (win->variant.palette_16bpp) { in s3c_fb_probe_win()
1218 win->palette.r.offset = 11; in s3c_fb_probe_win()
1219 win->palette.r.length = 5; in s3c_fb_probe_win()
1220 win->palette.g.offset = 5; in s3c_fb_probe_win()
1221 win->palette.g.length = 6; in s3c_fb_probe_win()
1222 win->palette.b.offset = 0; in s3c_fb_probe_win()
1223 win->palette.b.length = 5; in s3c_fb_probe_win()
1226 /* Set 8bpp or 8bpp and 1bit alpha */ in s3c_fb_probe_win()
1227 win->palette.r.offset = 16; in s3c_fb_probe_win()
1228 win->palette.r.length = 8; in s3c_fb_probe_win()
1229 win->palette.g.offset = 8; in s3c_fb_probe_win()
1230 win->palette.g.length = 8; in s3c_fb_probe_win()
1231 win->palette.b.offset = 0; in s3c_fb_probe_win()
1232 win->palette.b.length = 8; in s3c_fb_probe_win()
1235 /* setup the initial video mode from the window */ in s3c_fb_probe_win()
1236 initmode.xres = windata->xres; in s3c_fb_probe_win()
1237 initmode.yres = windata->yres; in s3c_fb_probe_win()
1238 fb_videomode_to_var(&fbinfo->var, &initmode); in s3c_fb_probe_win()
1240 fbinfo->fix.type = FB_TYPE_PACKED_PIXELS; in s3c_fb_probe_win()
1241 fbinfo->fix.accel = FB_ACCEL_NONE; in s3c_fb_probe_win()
1242 fbinfo->var.activate = FB_ACTIVATE_NOW; in s3c_fb_probe_win()
1243 fbinfo->var.vmode = FB_VMODE_NONINTERLACED; in s3c_fb_probe_win()
1244 fbinfo->var.bits_per_pixel = windata->default_bpp; in s3c_fb_probe_win()
1245 fbinfo->fbops = &s3c_fb_ops; in s3c_fb_probe_win()
1246 fbinfo->flags = FBINFO_FLAG_DEFAULT; in s3c_fb_probe_win()
1247 fbinfo->pseudo_palette = &win->pseudo_palette; in s3c_fb_probe_win()
1251 ret = s3c_fb_check_var(&fbinfo->var, fbinfo); in s3c_fb_probe_win()
1253 dev_err(sfb->dev, "check_var failed on initial video params\n"); in s3c_fb_probe_win()
1259 ret = fb_alloc_cmap(&fbinfo->cmap, win->variant.palette_sz, 1); in s3c_fb_probe_win()
1261 fb_set_cmap(&fbinfo->cmap, fbinfo); in s3c_fb_probe_win()
1263 dev_err(sfb->dev, "failed to allocate fb cmap\n"); in s3c_fb_probe_win()
1267 dev_dbg(sfb->dev, "about to register framebuffer\n"); in s3c_fb_probe_win()
1273 dev_err(sfb->dev, "failed to register framebuffer\n"); in s3c_fb_probe_win()
1277 dev_info(sfb->dev, "window %d: fb %s\n", win_no, fbinfo->fix.id); in s3c_fb_probe_win()
1283 * s3c_fb_set_rgb_timing() - set video timing for rgb interface.
1290 struct fb_videomode *vmode = sfb->pdata->vtiming; in s3c_fb_set_rgb_timing()
1291 void __iomem *regs = sfb->regs; in s3c_fb_set_rgb_timing()
1295 if (!vmode->pixclock) in s3c_fb_set_rgb_timing()
1298 clkdiv = s3c_fb_calc_pixclk(sfb, vmode->pixclock); in s3c_fb_set_rgb_timing()
1300 data = sfb->pdata->vidcon0; in s3c_fb_set_rgb_timing()
1304 data |= VIDCON0_CLKVAL_F(clkdiv-1) | VIDCON0_CLKDIR; in s3c_fb_set_rgb_timing()
1308 if (sfb->variant.is_2443) in s3c_fb_set_rgb_timing()
1312 data = VIDTCON0_VBPD(vmode->upper_margin - 1) | in s3c_fb_set_rgb_timing()
1313 VIDTCON0_VFPD(vmode->lower_margin - 1) | in s3c_fb_set_rgb_timing()
1314 VIDTCON0_VSPW(vmode->vsync_len - 1); in s3c_fb_set_rgb_timing()
1315 writel(data, regs + sfb->variant.vidtcon); in s3c_fb_set_rgb_timing()
1317 data = VIDTCON1_HBPD(vmode->left_margin - 1) | in s3c_fb_set_rgb_timing()
1318 VIDTCON1_HFPD(vmode->right_margin - 1) | in s3c_fb_set_rgb_timing()
1319 VIDTCON1_HSPW(vmode->hsync_len - 1); in s3c_fb_set_rgb_timing()
1320 writel(data, regs + sfb->variant.vidtcon + 4); in s3c_fb_set_rgb_timing()
1322 data = VIDTCON2_LINEVAL(vmode->yres - 1) | in s3c_fb_set_rgb_timing()
1323 VIDTCON2_HOZVAL(vmode->xres - 1) | in s3c_fb_set_rgb_timing()
1324 VIDTCON2_LINEVAL_E(vmode->yres - 1) | in s3c_fb_set_rgb_timing()
1325 VIDTCON2_HOZVAL_E(vmode->xres - 1); in s3c_fb_set_rgb_timing()
1326 writel(data, regs + sfb->variant.vidtcon + 8); in s3c_fb_set_rgb_timing()
1330 * s3c_fb_clear_win() - clear hardware window registers.
1338 void __iomem *regs = sfb->regs; in s3c_fb_clear_win()
1341 writel(0, regs + sfb->variant.wincon + (win * 4)); in s3c_fb_clear_win()
1342 writel(0, regs + VIDOSD_A(win, sfb->variant)); in s3c_fb_clear_win()
1343 writel(0, regs + VIDOSD_B(win, sfb->variant)); in s3c_fb_clear_win()
1344 writel(0, regs + VIDOSD_C(win, sfb->variant)); in s3c_fb_clear_win()
1346 if (sfb->variant.has_shadowcon) { in s3c_fb_clear_win()
1347 reg = readl(sfb->regs + SHADOWCON); in s3c_fb_clear_win()
1351 writel(reg, sfb->regs + SHADOWCON); in s3c_fb_clear_win()
1359 struct device *dev = &pdev->dev; in s3c_fb_probe()
1368 fbdrv = (struct s3c_fb_driverdata *)platid->driver_data; in s3c_fb_probe()
1370 if (fbdrv->variant.nr_windows > S3C_FB_MAX_WIN) { in s3c_fb_probe()
1372 return -EINVAL; in s3c_fb_probe()
1375 pd = dev_get_platdata(&pdev->dev); in s3c_fb_probe()
1378 return -EINVAL; in s3c_fb_probe()
1383 return -ENOMEM; in s3c_fb_probe()
1387 sfb->dev = dev; in s3c_fb_probe()
1388 sfb->pdata = pd; in s3c_fb_probe()
1389 sfb->variant = fbdrv->variant; in s3c_fb_probe()
1391 spin_lock_init(&sfb->slock); in s3c_fb_probe()
1393 sfb->bus_clk = devm_clk_get(dev, "lcd"); in s3c_fb_probe()
1394 if (IS_ERR(sfb->bus_clk)) { in s3c_fb_probe()
1396 return PTR_ERR(sfb->bus_clk); in s3c_fb_probe()
1399 clk_prepare_enable(sfb->bus_clk); in s3c_fb_probe()
1401 if (!sfb->variant.has_clksel) { in s3c_fb_probe()
1402 sfb->lcd_clk = devm_clk_get(dev, "sclk_fimd"); in s3c_fb_probe()
1403 if (IS_ERR(sfb->lcd_clk)) { in s3c_fb_probe()
1405 ret = PTR_ERR(sfb->lcd_clk); in s3c_fb_probe()
1409 clk_prepare_enable(sfb->lcd_clk); in s3c_fb_probe()
1412 pm_runtime_enable(sfb->dev); in s3c_fb_probe()
1414 sfb->regs = devm_platform_ioremap_resource(pdev, 0); in s3c_fb_probe()
1415 if (IS_ERR(sfb->regs)) { in s3c_fb_probe()
1416 ret = PTR_ERR(sfb->regs); in s3c_fb_probe()
1423 ret = -ENOENT; in s3c_fb_probe()
1426 sfb->irq_no = res->start; in s3c_fb_probe()
1427 ret = devm_request_irq(dev, sfb->irq_no, s3c_fb_irq, in s3c_fb_probe()
1434 dev_dbg(dev, "got resources (regs %p), probing windows\n", sfb->regs); in s3c_fb_probe()
1437 pm_runtime_get_sync(sfb->dev); in s3c_fb_probe()
1441 pd->setup_gpio(); in s3c_fb_probe()
1443 writel(pd->vidcon1, sfb->regs + VIDCON1); in s3c_fb_probe()
1445 /* set video clock running at under-run */ in s3c_fb_probe()
1446 if (sfb->variant.has_fixvclk) { in s3c_fb_probe()
1447 reg = readl(sfb->regs + VIDCON1); in s3c_fb_probe()
1450 writel(reg, sfb->regs + VIDCON1); in s3c_fb_probe()
1455 for (win = 0; win < fbdrv->variant.nr_windows; win++) in s3c_fb_probe()
1459 for (win = 0; win < (fbdrv->variant.nr_windows - 1); win++) { in s3c_fb_probe()
1460 void __iomem *regs = sfb->regs + sfb->variant.keycon; in s3c_fb_probe()
1471 for (win = 0; win < fbdrv->variant.nr_windows; win++) { in s3c_fb_probe()
1472 if (!pd->win[win]) in s3c_fb_probe()
1475 ret = s3c_fb_probe_win(sfb, win, fbdrv->win[win], in s3c_fb_probe()
1476 &sfb->windows[win]); in s3c_fb_probe()
1479 for (; win >= 0; win--) in s3c_fb_probe()
1480 s3c_fb_release_win(sfb, sfb->windows[win]); in s3c_fb_probe()
1486 pm_runtime_put_sync(sfb->dev); in s3c_fb_probe()
1491 pm_runtime_put_sync(sfb->dev); in s3c_fb_probe()
1494 pm_runtime_disable(sfb->dev); in s3c_fb_probe()
1496 if (!sfb->variant.has_clksel) in s3c_fb_probe()
1497 clk_disable_unprepare(sfb->lcd_clk); in s3c_fb_probe()
1500 clk_disable_unprepare(sfb->bus_clk); in s3c_fb_probe()
1506 * s3c_fb_remove() - Cleanup on module finalisation
1517 pm_runtime_get_sync(sfb->dev); in s3c_fb_remove()
1520 if (sfb->windows[win]) in s3c_fb_remove()
1521 s3c_fb_release_win(sfb, sfb->windows[win]); in s3c_fb_remove()
1523 if (!sfb->variant.has_clksel) in s3c_fb_remove()
1524 clk_disable_unprepare(sfb->lcd_clk); in s3c_fb_remove()
1526 clk_disable_unprepare(sfb->bus_clk); in s3c_fb_remove()
1528 pm_runtime_put_sync(sfb->dev); in s3c_fb_remove()
1529 pm_runtime_disable(sfb->dev); in s3c_fb_remove()
1541 pm_runtime_get_sync(sfb->dev); in s3c_fb_suspend()
1543 for (win_no = S3C_FB_MAX_WIN - 1; win_no >= 0; win_no--) { in s3c_fb_suspend()
1544 win = sfb->windows[win_no]; in s3c_fb_suspend()
1548 /* use the blank function to push into power-down */ in s3c_fb_suspend()
1549 s3c_fb_blank(FB_BLANK_POWERDOWN, win->fbinfo); in s3c_fb_suspend()
1552 if (!sfb->variant.has_clksel) in s3c_fb_suspend()
1553 clk_disable_unprepare(sfb->lcd_clk); in s3c_fb_suspend()
1555 clk_disable_unprepare(sfb->bus_clk); in s3c_fb_suspend()
1557 pm_runtime_put_sync(sfb->dev); in s3c_fb_suspend()
1565 struct s3c_fb_platdata *pd = sfb->pdata; in s3c_fb_resume()
1570 pm_runtime_get_sync(sfb->dev); in s3c_fb_resume()
1572 clk_prepare_enable(sfb->bus_clk); in s3c_fb_resume()
1574 if (!sfb->variant.has_clksel) in s3c_fb_resume()
1575 clk_prepare_enable(sfb->lcd_clk); in s3c_fb_resume()
1578 pd->setup_gpio(); in s3c_fb_resume()
1579 writel(pd->vidcon1, sfb->regs + VIDCON1); in s3c_fb_resume()
1581 /* set video clock running at under-run */ in s3c_fb_resume()
1582 if (sfb->variant.has_fixvclk) { in s3c_fb_resume()
1583 reg = readl(sfb->regs + VIDCON1); in s3c_fb_resume()
1586 writel(reg, sfb->regs + VIDCON1); in s3c_fb_resume()
1590 for (win_no = 0; win_no < sfb->variant.nr_windows; win_no++) in s3c_fb_resume()
1593 for (win_no = 0; win_no < sfb->variant.nr_windows - 1; win_no++) { in s3c_fb_resume()
1594 void __iomem *regs = sfb->regs + sfb->variant.keycon; in s3c_fb_resume()
1595 win = sfb->windows[win_no]; in s3c_fb_resume()
1610 win = sfb->windows[win_no]; in s3c_fb_resume()
1615 s3c_fb_set_par(win->fbinfo); in s3c_fb_resume()
1618 pm_runtime_put_sync(sfb->dev); in s3c_fb_resume()
1629 if (!sfb->variant.has_clksel) in s3c_fb_runtime_suspend()
1630 clk_disable_unprepare(sfb->lcd_clk); in s3c_fb_runtime_suspend()
1632 clk_disable_unprepare(sfb->bus_clk); in s3c_fb_runtime_suspend()
1640 struct s3c_fb_platdata *pd = sfb->pdata; in s3c_fb_runtime_resume()
1642 clk_prepare_enable(sfb->bus_clk); in s3c_fb_runtime_resume()
1644 if (!sfb->variant.has_clksel) in s3c_fb_runtime_resume()
1645 clk_prepare_enable(sfb->lcd_clk); in s3c_fb_runtime_resume()
1648 pd->setup_gpio(); in s3c_fb_runtime_resume()
1649 writel(pd->vidcon1, sfb->regs + VIDCON1); in s3c_fb_runtime_resume()
1781 .name = "s3c-fb",
1784 .name = "s3c2443-fb",
1802 .name = "s3c-fb",
1812 MODULE_ALIAS("platform:s3c-fb");