^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) ================================================
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) SH7760/SH7763 integrated LCDC Framebuffer driver
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) ================================================
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) 0. Overview
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) -----------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) The SH7760/SH7763 have an integrated LCD Display controller (LCDC) which
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) supports (in theory) resolutions ranging from 1x1 to 1024x1024,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) with color depths ranging from 1 to 16 bits, on STN, DSTN and TFT Panels.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) Caveats:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) * Framebuffer memory must be a large chunk allocated at the top
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) of Area3 (HW requirement). Because of this requirement you should NOT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) make the driver a module since at runtime it may become impossible to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) get a large enough contiguous chunk of memory.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) * The driver does not support changing resolution while loaded
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) (displays aren't hotpluggable anyway)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) * Heavy flickering may be observed
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) a) if you're using 15/16bit color modes at >= 640x480 px resolutions,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) b) during PCMCIA (or any other slow bus) activity.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) * Rotation works only 90degress clockwise, and only if horizontal
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) resolution is <= 320 pixels.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) Files:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) - drivers/video/sh7760fb.c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) - include/asm-sh/sh7760fb.h
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) - Documentation/fb/sh7760fb.rst
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) 1. Platform setup
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) -----------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) SH7760:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) Video data is fetched via the DMABRG DMA engine, so you have to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) configure the SH DMAC for DMABRG mode (write 0x94808080 to the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) DMARSRA register somewhere at boot).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) PFC registers PCCR and PCDR must be set to peripheral mode.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) (write zeros to both).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) The driver does NOT do the above for you since board setup is, well, job
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) of the board setup code.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) 2. Panel definitions
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) --------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) The LCDC must explicitly be told about the type of LCD panel
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) attached. Data must be wrapped in a "struct sh7760fb_platdata" and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) passed to the driver as platform_data.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) Suggest you take a closer look at the SH7760 Manual, Section 30.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) (http://documentation.renesas.com/eng/products/mpumcu/e602291_sh7760.pdf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) The following code illustrates what needs to be done to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) get the framebuffer working on a 640x480 TFT::
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) #include <linux/fb.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) #include <asm/sh7760fb.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) * NEC NL6440bc26-01 640x480 TFT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) * dotclock 25175 kHz
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) * Xres 640 Yres 480
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) * Htotal 800 Vtotal 525
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) * HsynStart 656 VsynStart 490
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) * HsynLenn 30 VsynLenn 2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) * The linux framebuffer layer does not use the syncstart/synclen
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) * values but right/left/upper/lower margin values. The comments
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) * for the x_margin explain how to calculate those from given
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) * panel sync timings.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) static struct fb_videomode nl6448bc26 = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) .name = "NL6448BC26",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) .refresh = 60,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) .xres = 640,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) .yres = 480,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) .pixclock = 39683, /* in picoseconds! */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) .hsync_len = 30,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) .vsync_len = 2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) .left_margin = 114, /* HTOT - (HSYNSLEN + HSYNSTART) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) .right_margin = 16, /* HSYNSTART - XRES */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) .upper_margin = 33, /* VTOT - (VSYNLEN + VSYNSTART) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) .lower_margin = 10, /* VSYNSTART - YRES */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) .vmode = FB_VMODE_NONINTERLACED,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) .flag = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) static struct sh7760fb_platdata sh7760fb_nl6448 = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) .def_mode = &nl6448bc26,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) .ldmtr = LDMTR_TFT_COLOR_16, /* 16bit TFT panel */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) .lddfr = LDDFR_8BPP, /* we want 8bit output */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) .ldpmmr = 0x0070,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) .ldpspr = 0x0500,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) .ldaclnr = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) .ldickr = LDICKR_CLKSRC(LCDC_CLKSRC_EXTERNAL) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) LDICKR_CLKDIV(1),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) .rotate = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) .novsync = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) .blank = NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) /* SH7760:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) * 0xFE300800: 256 * 4byte xRGB palette ram
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) * 0xFE300C00: 42 bytes ctrl registers
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) static struct resource sh7760_lcdc_res[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) [0] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) .start = 0xFE300800,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) .end = 0xFE300CFF,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) .flags = IORESOURCE_MEM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) [1] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) .start = 65,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) .end = 65,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) .flags = IORESOURCE_IRQ,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) static struct platform_device sh7760_lcdc_dev = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) .dev = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) .platform_data = &sh7760fb_nl6448,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) .name = "sh7760-lcdc",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) .id = -1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) .resource = sh7760_lcdc_res,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) .num_resources = ARRAY_SIZE(sh7760_lcdc_res),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) };