Date:2011-06-06 05:41:21 (12 years 9 months ago)
Author:Maarten ter Huurne
Commit:a0570c5a4352b42e3e62ddce75e24db15650bfa7
Message:MIPS: JZ4740: SLCD framebufer driver

This driver sends the frame buffer to a smart LCD controller,
that is a controller with its own video memory.
It is a squashed version of development done in the jz-3.5 branch.
Files: arch/mips/include/asm/mach-jz4740/gpio.h (2 diffs)
arch/mips/include/asm/mach-jz4740/jz4740_fb.h (2 diffs)
drivers/video/Kconfig (1 diff)
drivers/video/Makefile (1 diff)
drivers/video/jz4740_fb.c (1 diff)
drivers/video/jz4740_lcd.h (1 diff)
drivers/video/jz4740_slcd.h (1 diff)
drivers/video/jz4740_slcd_fb.c (1 diff)
drivers/video/jz4740_slcd_panels.c (1 diff)

Change Details

arch/mips/include/asm/mach-jz4740/gpio.h
252252#define JZ_GPIO_MEM_WAIT JZ_GPIO_PORTC(27)
253253#define JZ_GPIO_MEM_FRE JZ_GPIO_PORTC(28)
254254#define JZ_GPIO_MEM_FWE JZ_GPIO_PORTC(29)
255/* Pins have different assignment in SLCD mode */
256#define JZ_GPIO_SLCD_RS JZ_GPIO_PORTC(19)
257#define JZ_GPIO_SLCD_CS JZ_GPIO_PORTC(20)
255258
256259#define JZ_GPIO_FUNC_LCD_DATA0 JZ_GPIO_FUNC1
257260#define JZ_GPIO_FUNC_LCD_DATA1 JZ_GPIO_FUNC1
...... 
283286#define JZ_GPIO_FUNC_MEM_WAIT JZ_GPIO_FUNC1
284287#define JZ_GPIO_FUNC_MEM_FRE JZ_GPIO_FUNC1
285288#define JZ_GPIO_FUNC_MEM_FWE JZ_GPIO_FUNC1
289#define JZ_GPIO_FUNC_SLCD_RS JZ_GPIO_FUNC1
290#define JZ_GPIO_FUNC_SLCD_CS JZ_GPIO_FUNC1
286291
287292
288293#define JZ_GPIO_MEM_ADDR19 JZ_GPIO_PORTB(22)
arch/mips/include/asm/mach-jz4740/jz4740_fb.h
3030    JZ_LCD_TYPE_DUAL_COLOR_STN = 10,
3131    JZ_LCD_TYPE_DUAL_MONOCHROME_STN = 11,
3232    JZ_LCD_TYPE_8BIT_SERIAL = 12,
33    JZ_LCD_TYPE_SMART_PARALLEL_8_BIT = 1 | (1 << 5),
34    JZ_LCD_TYPE_SMART_PARALLEL_16_BIT = 0 | (1 << 5),
35    JZ_LCD_TYPE_SMART_PARALLEL_18_BIT = 2 | (1 << 5),
36    JZ_LCD_TYPE_SMART_SERIAL_8_BIT = 1 | (3 << 5),
37    JZ_LCD_TYPE_SMART_SERIAL_16_BIT = 0 | (3 << 5),
38    JZ_LCD_TYPE_SMART_SERIAL_18_BIT = 2 | (3 << 5),
3339};
3440
3541#define JZ4740_FB_SPECIAL_TFT_CONFIG(start, stop) (((start) << 16) | (stop))
...... 
6268
6369    unsigned pixclk_falling_edge:1;
6470    unsigned date_enable_active_low:1;
71    unsigned chip_select_active_low:1;
72    unsigned register_select_active_low:1;
6573};
6674
6775#endif
drivers/video/Kconfig
24312431    help
24322432      Framebuffer support for the JZ4740 SoC.
24332433
2434config FB_JZ4740_SLCD
2435    tristate "JZ4740 Smart LCD framebuffer support"
2436    depends on FB && MACH_JZ4740
2437    select FB_SYS_FILLRECT
2438    select FB_SYS_COPYAREA
2439    select FB_SYS_IMAGEBLIT
2440    help
2441      This is the frame buffer device driver for the JZ4740 Smart LCD controller.
2442      If you say Y here, please say N to 'JZ4740 LCD framebuffer support'.
2443
2444config JZ_SLCD_ILI9325
2445    bool "ILI9325 Smart LCD panel"
2446    depends on FB_JZ4740_SLCD
2447
2448config JZ_SLCD_ILI9331
2449    bool "ILI9331 Smart LCD panel"
2450    depends on FB_JZ4740_SLCD
2451
2452config JZ_SLCD_ILI9338
2453    bool "ILI9338 Smart LCD panel"
2454    depends on FB_JZ4740_SLCD
2455
24342456config FB_MXS
24352457    tristate "MXS LCD framebuffer support"
24362458    depends on FB && ARCH_MXS
drivers/video/Makefile
148148obj-$(CONFIG_FB_MSM) += msm/
149149obj-$(CONFIG_FB_NUC900) += nuc900fb.o
150150obj-$(CONFIG_FB_JZ4740) += jz4740_fb.o
151obj-$(CONFIG_FB_JZ4740_SLCD) += jz4740_slcd_fb.o jz4740_slcd_panels.o
151152obj-$(CONFIG_FB_PUV3_UNIGFX) += fb-puv3.o
152153
153154# Platform or fallback drivers go here
drivers/video/jz4740_fb.c
2929#include <asm/mach-jz4740/jz4740_fb.h>
3030#include <asm/mach-jz4740/gpio.h>
3131
32#define JZ_REG_LCD_CFG 0x00
33#define JZ_REG_LCD_VSYNC 0x04
34#define JZ_REG_LCD_HSYNC 0x08
35#define JZ_REG_LCD_VAT 0x0C
36#define JZ_REG_LCD_DAH 0x10
37#define JZ_REG_LCD_DAV 0x14
38#define JZ_REG_LCD_PS 0x18
39#define JZ_REG_LCD_CLS 0x1C
40#define JZ_REG_LCD_SPL 0x20
41#define JZ_REG_LCD_REV 0x24
42#define JZ_REG_LCD_CTRL 0x30
43#define JZ_REG_LCD_STATE 0x34
44#define JZ_REG_LCD_IID 0x38
45#define JZ_REG_LCD_DA0 0x40
46#define JZ_REG_LCD_SA0 0x44
47#define JZ_REG_LCD_FID0 0x48
48#define JZ_REG_LCD_CMD0 0x4C
49#define JZ_REG_LCD_DA1 0x50
50#define JZ_REG_LCD_SA1 0x54
51#define JZ_REG_LCD_FID1 0x58
52#define JZ_REG_LCD_CMD1 0x5C
53
54#define JZ_LCD_CFG_SLCD BIT(31)
55#define JZ_LCD_CFG_PS_DISABLE BIT(23)
56#define JZ_LCD_CFG_CLS_DISABLE BIT(22)
57#define JZ_LCD_CFG_SPL_DISABLE BIT(21)
58#define JZ_LCD_CFG_REV_DISABLE BIT(20)
59#define JZ_LCD_CFG_HSYNCM BIT(19)
60#define JZ_LCD_CFG_PCLKM BIT(18)
61#define JZ_LCD_CFG_INV BIT(17)
62#define JZ_LCD_CFG_SYNC_DIR BIT(16)
63#define JZ_LCD_CFG_PS_POLARITY BIT(15)
64#define JZ_LCD_CFG_CLS_POLARITY BIT(14)
65#define JZ_LCD_CFG_SPL_POLARITY BIT(13)
66#define JZ_LCD_CFG_REV_POLARITY BIT(12)
67#define JZ_LCD_CFG_HSYNC_ACTIVE_LOW BIT(11)
68#define JZ_LCD_CFG_PCLK_FALLING_EDGE BIT(10)
69#define JZ_LCD_CFG_DE_ACTIVE_LOW BIT(9)
70#define JZ_LCD_CFG_VSYNC_ACTIVE_LOW BIT(8)
71#define JZ_LCD_CFG_18_BIT BIT(7)
72#define JZ_LCD_CFG_PDW (BIT(5) | BIT(4))
73#define JZ_LCD_CFG_MODE_MASK 0xf
74
75#define JZ_LCD_CTRL_BURST_4 (0x0 << 28)
76#define JZ_LCD_CTRL_BURST_8 (0x1 << 28)
77#define JZ_LCD_CTRL_BURST_16 (0x2 << 28)
78#define JZ_LCD_CTRL_RGB555 BIT(27)
79#define JZ_LCD_CTRL_OFUP BIT(26)
80#define JZ_LCD_CTRL_FRC_GRAYSCALE_16 (0x0 << 24)
81#define JZ_LCD_CTRL_FRC_GRAYSCALE_4 (0x1 << 24)
82#define JZ_LCD_CTRL_FRC_GRAYSCALE_2 (0x2 << 24)
83#define JZ_LCD_CTRL_PDD_MASK (0xff << 16)
84#define JZ_LCD_CTRL_EOF_IRQ BIT(13)
85#define JZ_LCD_CTRL_SOF_IRQ BIT(12)
86#define JZ_LCD_CTRL_OFU_IRQ BIT(11)
87#define JZ_LCD_CTRL_IFU0_IRQ BIT(10)
88#define JZ_LCD_CTRL_IFU1_IRQ BIT(9)
89#define JZ_LCD_CTRL_DD_IRQ BIT(8)
90#define JZ_LCD_CTRL_QDD_IRQ BIT(7)
91#define JZ_LCD_CTRL_REVERSE_ENDIAN BIT(6)
92#define JZ_LCD_CTRL_LSB_FISRT BIT(5)
93#define JZ_LCD_CTRL_DISABLE BIT(4)
94#define JZ_LCD_CTRL_ENABLE BIT(3)
95#define JZ_LCD_CTRL_BPP_1 0x0
96#define JZ_LCD_CTRL_BPP_2 0x1
97#define JZ_LCD_CTRL_BPP_4 0x2
98#define JZ_LCD_CTRL_BPP_8 0x3
99#define JZ_LCD_CTRL_BPP_15_16 0x4
100#define JZ_LCD_CTRL_BPP_18_24 0x5
101
102#define JZ_LCD_CMD_SOF_IRQ BIT(31)
103#define JZ_LCD_CMD_EOF_IRQ BIT(30)
104#define JZ_LCD_CMD_ENABLE_PAL BIT(28)
105
106#define JZ_LCD_SYNC_MASK 0x3ff
107
108#define JZ_LCD_STATE_QUICK_DISABLED BIT(7)
109#define JZ_LCD_STATE_EOF BIT(5)
110#define JZ_LCD_STATE_SOF BIT(4)
111#define JZ_LCD_STATE_OUT_FIFO_UNDERRUN BIT(3)
112#define JZ_LCD_STATE_FIFO0_UNDERRUN BIT(2)
113#define JZ_LCD_STATE_FIFO1_UNDERRUN BIT(1)
114#define JZ_LCD_STATE_DISABLED BIT(0)
32#include "jz4740_lcd.h"
11533
11634struct jzfb_framedesc {
11735    uint32_t next;
drivers/video/jz4740_lcd.h
1/*
2 * Copyright (C) 2009, Lars-Peter Clausen <lars@metafoo.de>
3 * JZ4720/JZ4740 SoC LCD framebuffer driver
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published by the
7 * Free Software Foundation; either version 2 of the License, or (at your
8 * option) any later version.
9 *
10 * You should have received a copy of the GNU General Public License along
11 * with this program; if not, write to the Free Software Foundation, Inc.,
12 * 675 Mass Ave, Cambridge, MA 02139, USA.
13 *
14 */
15
16#ifndef __JZ4740_LCD_H__
17#define __JZ4740_LCD_H__
18
19#include <linux/bitops.h>
20
21#define JZ_REG_LCD_CFG 0x00
22#define JZ_REG_LCD_VSYNC 0x04
23#define JZ_REG_LCD_HSYNC 0x08
24#define JZ_REG_LCD_VAT 0x0C
25#define JZ_REG_LCD_DAH 0x10
26#define JZ_REG_LCD_DAV 0x14
27#define JZ_REG_LCD_PS 0x18
28#define JZ_REG_LCD_CLS 0x1C
29#define JZ_REG_LCD_SPL 0x20
30#define JZ_REG_LCD_REV 0x24
31#define JZ_REG_LCD_CTRL 0x30
32#define JZ_REG_LCD_STATE 0x34
33#define JZ_REG_LCD_IID 0x38
34#define JZ_REG_LCD_DA0 0x40
35#define JZ_REG_LCD_SA0 0x44
36#define JZ_REG_LCD_FID0 0x48
37#define JZ_REG_LCD_CMD0 0x4C
38#define JZ_REG_LCD_DA1 0x50
39#define JZ_REG_LCD_SA1 0x54
40#define JZ_REG_LCD_FID1 0x58
41#define JZ_REG_LCD_CMD1 0x5C
42
43#define JZ_LCD_CFG_SLCD BIT(31)
44#define JZ_LCD_CFG_PS_DISABLE BIT(23)
45#define JZ_LCD_CFG_CLS_DISABLE BIT(22)
46#define JZ_LCD_CFG_SPL_DISABLE BIT(21)
47#define JZ_LCD_CFG_REV_DISABLE BIT(20)
48#define JZ_LCD_CFG_HSYNCM BIT(19)
49#define JZ_LCD_CFG_PCLKM BIT(18)
50#define JZ_LCD_CFG_INV BIT(17)
51#define JZ_LCD_CFG_SYNC_DIR BIT(16)
52#define JZ_LCD_CFG_PS_POLARITY BIT(15)
53#define JZ_LCD_CFG_CLS_POLARITY BIT(14)
54#define JZ_LCD_CFG_SPL_POLARITY BIT(13)
55#define JZ_LCD_CFG_REV_POLARITY BIT(12)
56#define JZ_LCD_CFG_HSYNC_ACTIVE_LOW BIT(11)
57#define JZ_LCD_CFG_PCLK_FALLING_EDGE BIT(10)
58#define JZ_LCD_CFG_DE_ACTIVE_LOW BIT(9)
59#define JZ_LCD_CFG_VSYNC_ACTIVE_LOW BIT(8)
60#define JZ_LCD_CFG_18_BIT BIT(7)
61#define JZ_LCD_CFG_PDW (BIT(5) | BIT(4))
62#define JZ_LCD_CFG_MODE_MASK 0xf
63
64#define JZ_LCD_CTRL_BURST_4 (0x0 << 28)
65#define JZ_LCD_CTRL_BURST_8 (0x1 << 28)
66#define JZ_LCD_CTRL_BURST_16 (0x2 << 28)
67#define JZ_LCD_CTRL_RGB555 BIT(27)
68#define JZ_LCD_CTRL_OFUP BIT(26)
69#define JZ_LCD_CTRL_FRC_GRAYSCALE_16 (0x0 << 24)
70#define JZ_LCD_CTRL_FRC_GRAYSCALE_4 (0x1 << 24)
71#define JZ_LCD_CTRL_FRC_GRAYSCALE_2 (0x2 << 24)
72#define JZ_LCD_CTRL_PDD_MASK (0xff << 16)
73#define JZ_LCD_CTRL_EOF_IRQ BIT(13)
74#define JZ_LCD_CTRL_SOF_IRQ BIT(12)
75#define JZ_LCD_CTRL_OFU_IRQ BIT(11)
76#define JZ_LCD_CTRL_IFU0_IRQ BIT(10)
77#define JZ_LCD_CTRL_IFU1_IRQ BIT(9)
78#define JZ_LCD_CTRL_DD_IRQ BIT(8)
79#define JZ_LCD_CTRL_QDD_IRQ BIT(7)
80#define JZ_LCD_CTRL_REVERSE_ENDIAN BIT(6)
81#define JZ_LCD_CTRL_LSB_FISRT BIT(5)
82#define JZ_LCD_CTRL_DISABLE BIT(4)
83#define JZ_LCD_CTRL_ENABLE BIT(3)
84#define JZ_LCD_CTRL_BPP_1 0x0
85#define JZ_LCD_CTRL_BPP_2 0x1
86#define JZ_LCD_CTRL_BPP_4 0x2
87#define JZ_LCD_CTRL_BPP_8 0x3
88#define JZ_LCD_CTRL_BPP_15_16 0x4
89#define JZ_LCD_CTRL_BPP_18_24 0x5
90
91#define JZ_LCD_CMD_SOF_IRQ BIT(31)
92#define JZ_LCD_CMD_EOF_IRQ BIT(30)
93#define JZ_LCD_CMD_ENABLE_PAL BIT(28)
94
95#define JZ_LCD_SYNC_MASK 0x3ff
96
97#define JZ_LCD_STATE_QUICK_DISABLED BIT(7)
98#define JZ_LCD_STATE_EOF BIT(5)
99#define JZ_LCD_STATE_SOF BIT(4)
100#define JZ_LCD_STATE_OUT_FIFO_UNDERRUN BIT(3)
101#define JZ_LCD_STATE_FIFO0_UNDERRUN BIT(2)
102#define JZ_LCD_STATE_FIFO1_UNDERRUN BIT(1)
103#define JZ_LCD_STATE_DISABLED BIT(0)
104
105#endif /*__JZ4740_LCD_H__*/
drivers/video/jz4740_slcd.h
1/*
2 * linux/drivers/video/jz4740_slcd.h
3 * -- LCD panel definitions for Ingenic On-Chip SLCD frame buffer device
4 *
5 * Copyright (C) 2005-2007, Ingenic Semiconductor Inc.
6 * Copyright (C) 2010, Maarten ter Huurne <maarten@treewalker.org>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11 *
12 */
13
14#ifndef __JZ4740_SLCD_H__
15#define __JZ4740_SLCD_H__
16
17#include <asm/mach-jz4740/base.h>
18#include <linux/gpio.h>
19#include <linux/mutex.h>
20#include <linux/workqueue.h>
21
22/*************************************************************************
23 * SLCD (Smart LCD Controller)
24 *************************************************************************/
25
26#define JZ_REG_SLCD_CFG 0xA0 /* SLCD Configure Register */
27#define JZ_REG_SLCD_CTRL 0xA4 /* SLCD Control Register */
28#define JZ_REG_SLCD_STATE 0xA8 /* SLCD Status Register */
29#define JZ_REG_SLCD_DATA 0xAC /* SLCD Data Register */
30#define JZ_REG_SLCD_FIFO 0xB0 /* SLCD FIFO Register */
31
32/* SLCD Configure Register */
33#define SLCD_CFG_BURST_BIT 14
34#define SLCD_CFG_BURST_MASK (0x3 << SLCD_CFG_BURST_BIT)
35  #define SLCD_CFG_BURST_4_WORD (0 << SLCD_CFG_BURST_BIT)
36  #define SLCD_CFG_BURST_8_WORD (1 << SLCD_CFG_BURST_BIT)
37#define SLCD_CFG_DWIDTH_BIT 10
38#define SLCD_CFG_DWIDTH_MASK (0x7 << SLCD_CFG_DWIDTH_BIT)
39  #define SLCD_CFG_DWIDTH_18 (0 << SLCD_CFG_DWIDTH_BIT)
40  #define SLCD_CFG_DWIDTH_16 (1 << SLCD_CFG_DWIDTH_BIT)
41  #define SLCD_CFG_DWIDTH_8_x3 (2 << SLCD_CFG_DWIDTH_BIT)
42  #define SLCD_CFG_DWIDTH_8_x2 (3 << SLCD_CFG_DWIDTH_BIT)
43  #define SLCD_CFG_DWIDTH_8_x1 (4 << SLCD_CFG_DWIDTH_BIT)
44  #define SLCD_CFG_DWIDTH_9_x2 (7 << SLCD_CFG_DWIDTH_BIT)
45#define SLCD_CFG_CWIDTH_BIT 8
46#define SLCD_CFG_CWIDTH_MASK (0x3 << SLCD_CFG_CWIDTH_BIT)
47  #define SLCD_CFG_CWIDTH_16BIT (0 << SLCD_CFG_CWIDTH_BIT)
48  #define SLCD_CFG_CWIDTH_8BIT (1 << SLCD_CFG_CWIDTH_BIT)
49  #define SLCD_CFG_CWIDTH_18BIT (2 << SLCD_CFG_CWIDTH_BIT)
50#define SLCD_CFG_CS_ACTIVE_LOW (0 << 4)
51#define SLCD_CFG_CS_ACTIVE_HIGH (1 << 4)
52#define SLCD_CFG_RS_CMD_LOW (0 << 3)
53#define SLCD_CFG_RS_CMD_HIGH (1 << 3)
54#define SLCD_CFG_CLK_ACTIVE_FALLING (0 << 1)
55#define SLCD_CFG_CLK_ACTIVE_RISING (1 << 1)
56#define SLCD_CFG_TYPE_PARALLEL (0 << 0)
57#define SLCD_CFG_TYPE_SERIAL (1 << 0)
58
59/* SLCD Control Register */
60#define SLCD_CTRL_DMA_EN (1 << 0)
61
62/* SLCD Status Register */
63#define SLCD_STATE_BUSY (1 << 0)
64
65/* SLCD Data Register */
66#define SLCD_DATA_RS_DATA (0 << 31)
67#define SLCD_DATA_RS_COMMAND (1 << 31)
68
69/* SLCD FIFO Register */
70#define SLCD_FIFO_RS_DATA (0 << 31)
71#define SLCD_FIFO_RS_COMMAND (1 << 31)
72
73/*************************************************************************/
74
75struct jzfb_framedesc {
76    uint32_t next;
77    uint32_t addr;
78    uint32_t id;
79    uint32_t cmd;
80} __attribute__((packed));
81
82struct jzfb {
83    struct fb_info *fb;
84    struct platform_device *pdev;
85    void __iomem *base;
86    struct resource *mem;
87    struct jz4740_fb_platform_data *pdata;
88    const struct jz_slcd_panel *panel;
89
90    size_t vidmem_size;
91    void *vidmem;
92    dma_addr_t vidmem_phys;
93
94    size_t blackline_size;
95    void *blackline;
96    dma_addr_t blackline_phys;
97
98    struct jzfb_framedesc (*framedesc)[3];
99    dma_addr_t framedesc_phys;
100
101    struct jz4740_dma_chan *dma;
102    struct completion dma_completion;
103    unsigned refresh_on_pan:1;
104
105    struct clk *ldclk;
106    struct clk *lpclk;
107
108    unsigned int tv_out;
109    unsigned tv_out_vsync:1;
110
111    unsigned is_enabled:1;
112    struct mutex lock; /* Protecting against running enable/disable in paralell */
113
114    struct delayed_work refresh_work;
115
116    uint32_t pseudo_palette[16];
117#ifdef CONFIG_JZ_SLCD_ILI9338
118    unsigned int rgb[3];
119#endif
120};
121
122struct jz_slcd_panel {
123    /* request and configure GPIO pins */
124    int (*init)(struct jzfb *jzfb);
125    /* free GPIO pins */
126    void (*exit)(struct jzfb *jzfb);
127    /* activate, reset and initialize */
128    void (*enable)(struct jzfb *jzfb);
129    /* deactivate */
130    void (*disable)(struct jzfb *jzfb);
131    /* panel name */
132    const char *name;
133};
134
135const struct jz_slcd_panel *jz_slcd_panel_from_name(const char *name);
136const struct jz_slcd_panel *jz_slcd_panels_probe(struct jzfb *jzfb);
137
138#endif /*__JZ4740_SLCD_H__*/
drivers/video/jz4740_slcd_fb.c
1/*
2 * Copyright (C) 2009-2010, Lars-Peter Clausen <lars@metafoo.de>
3 * Copyright (C) 2010, Maarten ter Huurne <maarten@treewalker.org>
4 * JZ4720/JZ4740 SoC LCD framebuffer driver
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2 of the License, or (at your
9 * option) any later version.
10 *
11 * You should have received a copy of the GNU General Public License along
12 * with this program; if not, write to the Free Software Foundation, Inc.,
13 * 675 Mass Ave, Cambridge, MA 02139, USA.
14 *
15 */
16
17#include <linux/kernel.h>
18#include <linux/module.h>
19#include <linux/mutex.h>
20#include <linux/platform_device.h>
21
22#include <linux/clk.h>
23#include <linux/delay.h>
24
25#include <linux/console.h>
26#include <linux/fb.h>
27
28#include <linux/dma-mapping.h>
29
30#include <asm/mach-jz4740/dma.h>
31#include <asm/mach-jz4740/gpio.h>
32#include <asm/mach-jz4740/jz4740_fb.h>
33
34#include "jz4740_lcd.h"
35#include "jz4740_slcd.h"
36
37#define FB_A320TV_OFF 0
38#define FB_A320TV_NTSC 1
39#define FB_A320TV_PAL50 2
40#define FB_A320TV_PAL60 3
41#define FB_A320TV_PAL_M 4
42#define FB_A320TV_LAST 4
43
44static const char *jzfb_tv_out_norm[] = {
45    "off", "ntsc", "pal", "pal-60", "pal-m",
46};
47
48static struct fb_fix_screeninfo jzfb_fix __devinitdata = {
49    .id = "JZ4740 SLCD FB",
50    .type = FB_TYPE_PACKED_PIXELS,
51    .visual = FB_VISUAL_TRUECOLOR,
52    .xpanstep = 0,
53    .ypanstep = 1,
54    .ywrapstep = 0,
55    .accel = FB_ACCEL_NONE,
56};
57
58const static struct jz_gpio_bulk_request jz_slcd_ctrl_pins[] = {
59    JZ_GPIO_BULK_PIN(LCD_PCLK),
60    JZ_GPIO_BULK_PIN(SLCD_RS),
61    JZ_GPIO_BULK_PIN(SLCD_CS),
62};
63
64const static struct jz_gpio_bulk_request jz_slcd_data_pins[] = {
65    JZ_GPIO_BULK_PIN(LCD_DATA0),
66    JZ_GPIO_BULK_PIN(LCD_DATA1),
67    JZ_GPIO_BULK_PIN(LCD_DATA2),
68    JZ_GPIO_BULK_PIN(LCD_DATA3),
69    JZ_GPIO_BULK_PIN(LCD_DATA4),
70    JZ_GPIO_BULK_PIN(LCD_DATA5),
71    JZ_GPIO_BULK_PIN(LCD_DATA6),
72    JZ_GPIO_BULK_PIN(LCD_DATA7),
73    JZ_GPIO_BULK_PIN(LCD_DATA8),
74    JZ_GPIO_BULK_PIN(LCD_DATA9),
75    JZ_GPIO_BULK_PIN(LCD_DATA10),
76    JZ_GPIO_BULK_PIN(LCD_DATA11),
77    JZ_GPIO_BULK_PIN(LCD_DATA12),
78    JZ_GPIO_BULK_PIN(LCD_DATA13),
79    JZ_GPIO_BULK_PIN(LCD_DATA14),
80    JZ_GPIO_BULK_PIN(LCD_DATA15),
81    JZ_GPIO_BULK_PIN(LCD_DATA16),
82    JZ_GPIO_BULK_PIN(LCD_DATA17),
83};
84
85static unsigned int jzfb_num_ctrl_pins(struct jzfb *jzfb)
86{
87    return ARRAY_SIZE(jz_slcd_ctrl_pins);
88}
89
90static unsigned int jzfb_num_data_pins(struct jzfb *jzfb)
91{
92    switch (jzfb->pdata->lcd_type) {
93    case JZ_LCD_TYPE_SMART_PARALLEL_8_BIT:
94        return 8;
95    case JZ_LCD_TYPE_SMART_PARALLEL_16_BIT:
96        return 16;
97    case JZ_LCD_TYPE_SMART_PARALLEL_18_BIT:
98        return 18;
99    default:
100        return 0;
101    }
102}
103
104static void jzfb_free_gpio_pins(struct jzfb *jzfb)
105{
106    jz_gpio_bulk_free(jz_slcd_ctrl_pins, jzfb_num_ctrl_pins(jzfb));
107    if (jzfb->pdata->lcd_type & (1 << 6)) {
108        /* serial */
109        jz_gpio_bulk_free(&jz_slcd_data_pins[15], 1);
110    } else {
111        /* parallel */
112        jz_gpio_bulk_free(jz_slcd_data_pins,
113                  jzfb_num_data_pins(jzfb));
114    }
115}
116
117static int jzfb_setcolreg(unsigned regno, unsigned red, unsigned green,
118            unsigned blue, unsigned transp, struct fb_info *fb)
119{
120    if (regno >= 16)
121        return -EINVAL;
122
123    red = (red * ((1 << fb->var.red.length ) - 1)) / ((1 << 16) - 1);
124    green = (green * ((1 << fb->var.green.length) - 1)) / ((1 << 16) - 1);
125    blue = (blue * ((1 << fb->var.blue.length ) - 1)) / ((1 << 16) - 1);
126
127    ((uint32_t *)fb->pseudo_palette)[regno] =
128        (red << fb->var.red.offset ) |
129        (green << fb->var.green.offset) |
130        (blue << fb->var.blue.offset );
131
132    return 0;
133}
134
135static int jzfb_get_controller_bpp(struct jzfb *jzfb)
136{
137    switch (jzfb->pdata->bpp) {
138    case 18:
139    case 24:
140        return 32;
141    case 15:
142        return 16;
143    default:
144        return jzfb->pdata->bpp;
145    }
146}
147
148static struct fb_videomode *jzfb_get_mode(struct jzfb *jzfb, struct fb_var_screeninfo *var)
149{
150    size_t i;
151    struct fb_videomode *mode = jzfb->pdata->modes;
152
153    for (i = 0; i < jzfb->pdata->num_modes; ++i, ++mode) {
154        if (mode->xres == var->xres && mode->yres == var->yres)
155            return mode;
156    }
157
158    return NULL;
159}
160
161static int jzfb_check_var(struct fb_var_screeninfo *var, struct fb_info *fb)
162{
163    struct jzfb *jzfb = fb->par;
164    struct fb_videomode *mode;
165
166    if (var->bits_per_pixel != jzfb_get_controller_bpp(jzfb) &&
167        var->bits_per_pixel != jzfb->pdata->bpp)
168        return -EINVAL;
169
170    mode = jzfb_get_mode(jzfb, var);
171    if (mode == NULL)
172        return -EINVAL;
173
174    fb_videomode_to_var(var, mode);
175
176    /* Reserve space for double buffering. */
177    var->yres_virtual = var->yres * 2;
178
179    switch (jzfb->pdata->bpp) {
180    case 8:
181        break;
182    case 15:
183        var->red.offset = 10;
184        var->red.length = 5;
185        var->green.offset = 5;
186        var->green.length = 5;
187        var->blue.offset = 0;
188        var->blue.length = 5;
189        break;
190    case 16:
191        var->red.offset = 11;
192        var->red.length = 5;
193        var->green.offset = 5;
194        var->green.length = 6;
195        var->blue.offset = 0;
196        var->blue.length = 5;
197        break;
198    case 18:
199        var->red.offset = 16;
200        var->red.length = 6;
201        var->green.offset = 8;
202        var->green.length = 6;
203        var->blue.offset = 0;
204        var->blue.length = 6;
205        var->bits_per_pixel = 32;
206        break;
207    case 32:
208    case 24:
209        var->transp.offset = 24;
210        var->transp.length = 8;
211        var->red.offset = 16;
212        var->red.length = 8;
213        var->green.offset = 8;
214        var->green.length = 8;
215        var->blue.offset = 0;
216        var->blue.length = 8;
217        var->bits_per_pixel = 32;
218        break;
219    default:
220        break;
221    }
222
223    return 0;
224}
225
226static void jzfb_disable_dma(struct jzfb *jzfb)
227{
228    jz4740_dma_disable(jzfb->dma);
229    while (readb(jzfb->base + JZ_REG_SLCD_STATE) & SLCD_STATE_BUSY);
230    writeb(readb(jzfb->base + JZ_REG_SLCD_CTRL) & ~SLCD_CTRL_DMA_EN,
231        jzfb->base + JZ_REG_SLCD_CTRL);
232}
233
234static struct jz4740_dma_config jzfb_slcd_dma_config = {
235    .src_width = JZ4740_DMA_WIDTH_32BIT,
236    .dst_width = JZ4740_DMA_WIDTH_16BIT,
237    .transfer_size = JZ4740_DMA_TRANSFER_SIZE_16BYTE,
238    .request_type = JZ4740_DMA_TYPE_SLCD,
239    .flags = JZ4740_DMA_SRC_AUTOINC,
240    .mode = JZ4740_DMA_MODE_BLOCK,
241};
242
243static void jzfb_upload_frame_dma(struct jzfb *jzfb)
244{
245    struct fb_info *fb = jzfb->fb;
246    struct fb_videomode *mode = fb->mode;
247    __u32 offset = fb->fix.line_length * fb->var.yoffset;
248    __u32 size = fb->fix.line_length * mode->yres;
249
250    /* Ensure that the data to be uploaded is in memory. */
251    dma_cache_sync(fb->device, jzfb->vidmem + offset, size,
252               DMA_TO_DEVICE);
253
254    jz4740_dma_set_src_addr(jzfb->dma, jzfb->vidmem_phys + offset);
255    jz4740_dma_set_dst_addr(jzfb->dma,
256                CPHYSADDR(jzfb->base + JZ_REG_SLCD_FIFO));
257    jz4740_dma_set_transfer_count(jzfb->dma, size);
258
259    while (readb(jzfb->base + JZ_REG_SLCD_STATE) & SLCD_STATE_BUSY);
260    writeb(readb(jzfb->base + JZ_REG_SLCD_CTRL) | SLCD_CTRL_DMA_EN,
261        jzfb->base + JZ_REG_SLCD_CTRL);
262    jz4740_dma_enable(jzfb->dma);
263}
264
265static void jzfb_upload_frame_cpu(struct jzfb *jzfb)
266{
267    const int num_pixels = jzfb->fb->mode->xres * jzfb->fb->mode->yres;
268    uint16_t *p = jzfb->vidmem;
269    int i;
270
271    jzfb_disable_dma(jzfb);
272    for (i = 0; i < num_pixels; i++) {
273        uint16_t rgb = *p++;
274        while (readb(jzfb->base + JZ_REG_SLCD_STATE) & SLCD_STATE_BUSY);
275        writel(SLCD_DATA_RS_DATA | rgb, jzfb->base + JZ_REG_SLCD_DATA);
276    }
277}
278
279static void jzfb_refresh_work(struct work_struct *work)
280{
281    struct jzfb *jzfb = container_of(work, struct jzfb, refresh_work.work);
282
283    mutex_lock(&jzfb->lock);
284    if (jzfb->is_enabled) {
285        if (1) {
286            int interval;
287
288            if (jzfb->dma_completion.done) {
289                if (jzfb->refresh_on_pan)
290                    interval = HZ / 5;
291                else
292                    interval = HZ / 60;
293                jzfb->refresh_on_pan = 0;
294
295                INIT_COMPLETION(jzfb->dma_completion);
296                jzfb_upload_frame_dma(jzfb);
297            } else
298                interval = HZ / 250;
299
300            schedule_delayed_work(&jzfb->refresh_work, interval);
301        } else {
302            jzfb_upload_frame_cpu(jzfb);
303            schedule_delayed_work(&jzfb->refresh_work, HZ / 10);
304        }
305    }
306    mutex_unlock(&jzfb->lock);
307}
308
309static void jzfb_refresh_work_complete(
310        struct jz4740_dma_chan *dma, int res, void *dev)
311{
312    struct jzfb *jzfb = dev_get_drvdata(dev);
313    complete_all(&jzfb->dma_completion);
314}
315
316static int jzfb_set_par(struct fb_info *info)
317{
318    struct jzfb *jzfb = info->par;
319    struct fb_var_screeninfo *var = &info->var;
320    struct fb_videomode *mode;
321    uint16_t slcd_cfg;
322
323    mode = jzfb_get_mode(jzfb, var);
324    if (mode == NULL)
325        return -EINVAL;
326
327    info->mode = mode;
328
329    slcd_cfg = SLCD_CFG_BURST_8_WORD;
330    /* command size */
331    slcd_cfg |= (jzfb->pdata->lcd_type & 3) << SLCD_CFG_CWIDTH_BIT;
332    /* data size */
333    if (jzfb->pdata->lcd_type & (1 << 6)) {
334        /* serial */
335        unsigned int num_bits;
336        switch (jzfb->pdata->lcd_type) {
337        case JZ_LCD_TYPE_SMART_SERIAL_8_BIT:
338            slcd_cfg |= SLCD_CFG_DWIDTH_8_x1;
339            num_bits = 8;
340            break;
341        case JZ_LCD_TYPE_SMART_SERIAL_16_BIT:
342            slcd_cfg |= SLCD_CFG_DWIDTH_16;
343            num_bits = 16;
344            break;
345        case JZ_LCD_TYPE_SMART_SERIAL_18_BIT:
346            slcd_cfg |= SLCD_CFG_DWIDTH_18;
347            num_bits = 18;
348            break;
349        default:
350            num_bits = 0;
351            break;
352        }
353        if (num_bits != jzfb->pdata->bpp) {
354            dev_err(&jzfb->pdev->dev,
355                "Data size (%d) does not match bpp (%d)\n",
356                num_bits, jzfb->pdata->bpp);
357        }
358        slcd_cfg |= SLCD_CFG_TYPE_SERIAL;
359    } else {
360        /* parallel */
361        switch (jzfb->pdata->bpp) {
362        case 8:
363            slcd_cfg |= SLCD_CFG_DWIDTH_8_x1;
364            break;
365        case 15:
366        case 16:
367            switch (jzfb->pdata->lcd_type) {
368            case JZ_LCD_TYPE_SMART_PARALLEL_8_BIT:
369                slcd_cfg |= SLCD_CFG_DWIDTH_8_x2;
370                break;
371            default:
372                slcd_cfg |= SLCD_CFG_DWIDTH_16;
373                break;
374            }
375            break;
376        case 18:
377            switch (jzfb->pdata->lcd_type) {
378            case JZ_LCD_TYPE_SMART_PARALLEL_8_BIT:
379                slcd_cfg |= SLCD_CFG_DWIDTH_8_x3;
380                break;
381            case JZ_LCD_TYPE_SMART_PARALLEL_16_BIT:
382                slcd_cfg |= SLCD_CFG_DWIDTH_9_x2;
383                break;
384            case JZ_LCD_TYPE_SMART_PARALLEL_18_BIT:
385                slcd_cfg |= SLCD_CFG_DWIDTH_18;
386                break;
387            default:
388                break;
389            }
390            break;
391        case 24:
392            slcd_cfg |= SLCD_CFG_DWIDTH_8_x3;
393            break;
394        default:
395            dev_err(&jzfb->pdev->dev,
396                "Unsupported value for bpp: %d\n",
397                jzfb->pdata->bpp);
398        }
399        slcd_cfg |= SLCD_CFG_TYPE_PARALLEL;
400    }
401    if (!jzfb->pdata->chip_select_active_low)
402        slcd_cfg |= SLCD_CFG_CS_ACTIVE_HIGH;
403    if (!jzfb->pdata->register_select_active_low)
404        slcd_cfg |= SLCD_CFG_RS_CMD_HIGH;
405    if (!jzfb->pdata->pixclk_falling_edge)
406        slcd_cfg |= SLCD_CFG_CLK_ACTIVE_RISING;
407
408#if 0
409    // TODO(MtH): Compute rate from refresh or vice versa.
410    if (mode->pixclock) {
411        rate = PICOS2KHZ(mode->pixclock) * 1000;
412        mode->refresh = rate / vt / ht;
413    } else {
414        if (jzfb->pdata->lcd_type == JZ_LCD_TYPE_8BIT_SERIAL)
415            rate = mode->refresh * (vt + 2 * mode->xres) * ht;
416        else
417            rate = mode->refresh * vt * ht;
418
419        mode->pixclock = KHZ2PICOS(rate / 1000);
420    }
421#endif
422
423    mutex_lock(&jzfb->lock);
424    if (!jzfb->is_enabled)
425        clk_enable(jzfb->ldclk);
426
427    // TODO(MtH): We should not change config while DMA might be running.
428    writew(slcd_cfg, jzfb->base + JZ_REG_SLCD_CFG);
429
430    if (!jzfb->is_enabled)
431        clk_disable(jzfb->ldclk);
432    mutex_unlock(&jzfb->lock);
433
434    // TODO(MtH): Use maximum transfer speed that panel can handle.
435    // ILI9325 can do 10 MHz.
436    clk_set_rate(jzfb->lpclk, 12000000);
437    clk_set_rate(jzfb->ldclk, 42000000);
438
439    return 0;
440}
441
442static void jzfb_enable(struct jzfb *jzfb)
443{
444    uint32_t ctrl;
445
446    clk_enable(jzfb->ldclk);
447
448    jz_gpio_bulk_resume(jz_slcd_ctrl_pins, jzfb_num_ctrl_pins(jzfb));
449    if (jzfb->pdata->lcd_type & (1 << 6)) {
450        /* serial */
451        jz_gpio_bulk_resume(&jz_slcd_data_pins[15], 1);
452    } else {
453        /* parallel */
454        jz_gpio_bulk_resume(jz_slcd_data_pins,
455                    jzfb_num_data_pins(jzfb));
456    }
457    jzfb_disable_dma(jzfb);
458    complete_all(&jzfb->dma_completion);
459    jzfb->panel->enable(jzfb);
460
461    ctrl = readl(jzfb->base + JZ_REG_LCD_CTRL);
462    ctrl |= JZ_LCD_CTRL_ENABLE;
463    ctrl &= ~JZ_LCD_CTRL_DISABLE;
464    writel(ctrl, jzfb->base + JZ_REG_LCD_CTRL);
465
466    schedule_delayed_work(&jzfb->refresh_work, 0);
467}
468
469static void jzfb_disable(struct jzfb *jzfb)
470{
471    /* It is safe but wasteful to call refresh_work() while disabled. */
472    cancel_delayed_work_sync(&jzfb->refresh_work);
473
474    /* Abort any DMA transfer that might be in progress and allow direct
475       writes to the panel. */
476    jzfb_disable_dma(jzfb);
477    complete_all(&jzfb->dma_completion);
478
479    jzfb->panel->disable(jzfb);
480    jz_gpio_bulk_suspend(jz_slcd_ctrl_pins, jzfb_num_ctrl_pins(jzfb));
481    if (jzfb->pdata->lcd_type & (1 << 6)) {
482        /* serial */
483        jz_gpio_bulk_suspend(&jz_slcd_data_pins[15], 1);
484    } else {
485        /* parallel */
486        jz_gpio_bulk_suspend(jz_slcd_data_pins,
487                     jzfb_num_data_pins(jzfb));
488    }
489
490    clk_disable(jzfb->ldclk);
491}
492
493static int jzfb_blank(int blank_mode, struct fb_info *info)
494{
495    struct jzfb *jzfb = info->par;
496    int ret = 0;
497    int new_enabled = (blank_mode == FB_BLANK_UNBLANK);
498
499    mutex_lock(&jzfb->lock);
500    if (new_enabled) {
501        if (!jzfb->is_enabled)
502            jzfb_enable(jzfb);
503    } else {
504        if (jzfb->is_enabled) {
505            /* No sleep in TV-out mode. */
506            if (jzfb->tv_out == FB_A320TV_OFF)
507                jzfb_disable(jzfb);
508            else
509                ret = -EBUSY;
510        }
511    }
512    if (!ret)
513        jzfb->is_enabled = new_enabled;
514    mutex_unlock(&jzfb->lock);
515
516    return ret;
517}
518
519static int jzfb_wait_for_vsync(struct fb_info *info)
520{
521    struct jzfb *jzfb = info->par;
522
523    if (jzfb->tv_out != FB_A320TV_OFF &&
524                !jzfb->tv_out_vsync)
525        return 0;
526    return wait_for_completion_interruptible(&jzfb->dma_completion);
527}
528
529static int jzfb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
530{
531    struct jzfb *jzfb = info->par;
532    info->var.yoffset = var->yoffset;
533
534    /* Ensure that the data to be uploaded is in memory. */
535    dma_cache_sync(&jzfb->pdev->dev, jzfb->vidmem
536                + info->fix.line_length * var->yoffset,
537                info->fix.line_length * var->yres,
538                DMA_TO_DEVICE);
539
540    /* update frame start address for TV-out mode */
541    (*jzfb->framedesc)[1].addr = jzfb->vidmem_phys
542                          + info->fix.line_length * var->yoffset;
543
544    jzfb_wait_for_vsync(info);
545
546    jzfb->refresh_on_pan = 1;
547    flush_delayed_work(&jzfb->refresh_work);
548    return 0;
549}
550
551static int jzfb_mmap(struct fb_info *info, struct vm_area_struct *vma)
552{
553    const unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;
554    const unsigned long size = vma->vm_end - vma->vm_start;
555
556    if (offset + size > info->fix.smem_len)
557        return -EINVAL;
558
559    if (remap_pfn_range(vma, vma->vm_start,
560                (info->fix.smem_start + offset) >> PAGE_SHIFT,
561                size, vma->vm_page_prot))
562        return -EAGAIN;
563
564    return 0;
565}
566
567static int jzfb_alloc_devmem(struct jzfb *jzfb)
568{
569    int max_linesize = 0, max_framesize = 0;
570    int bytes_per_pixel;
571    struct fb_videomode *mode = jzfb->pdata->modes;
572    void *page;
573    int i;
574
575    for (i = 0; i < jzfb->pdata->num_modes; ++mode, ++i) {
576        if (max_linesize < mode->xres)
577            max_linesize = mode->xres;
578        if (max_framesize < mode->xres * mode->yres)
579            max_framesize = mode->xres * mode->yres;
580    }
581
582    bytes_per_pixel = jzfb_get_controller_bpp(jzfb) >> 3;
583    max_linesize *= bytes_per_pixel;
584    max_framesize *= bytes_per_pixel;
585
586    jzfb->framedesc = dma_alloc_coherent(&jzfb->pdev->dev,
587                    sizeof(*jzfb->framedesc),
588                    &jzfb->framedesc_phys, GFP_KERNEL);
589    if (!jzfb->framedesc)
590        return -ENOMEM;
591
592    jzfb->blackline_size = max_linesize;
593    jzfb->blackline = dma_alloc_coherent(&jzfb->pdev->dev,
594                         jzfb->blackline_size,
595                         &jzfb->blackline_phys, GFP_KERNEL);
596    if (!jzfb->blackline)
597        goto err_free_framedesc;
598
599    /* Set the black line to black... */
600    memset(jzfb->blackline, 0, jzfb->blackline_size);
601
602    /* reserve memory for two frames to allow double buffering */
603    jzfb->vidmem_size = PAGE_ALIGN(max_framesize * 2);
604    jzfb->vidmem = dma_alloc_coherent(&jzfb->pdev->dev,
605                        jzfb->vidmem_size,
606                        &jzfb->vidmem_phys, GFP_KERNEL);
607
608    if (!jzfb->vidmem)
609        goto err_free_blackline;
610
611    for (page = jzfb->vidmem;
612         page < jzfb->vidmem + PAGE_ALIGN(jzfb->vidmem_size);
613         page += PAGE_SIZE) {
614        SetPageReserved(virt_to_page(page));
615    }
616
617    for (i = 0; i < 3; i++)
618        (*jzfb->framedesc)[i].next = jzfb->framedesc_phys
619                + ((i + 1) % 3) * sizeof(struct jzfb_framedesc);
620    (*jzfb->framedesc)[0].addr = (*jzfb->framedesc)[2].addr =
621            jzfb->blackline_phys;
622    (*jzfb->framedesc)[0].id = 0xdadabeeb;
623    (*jzfb->framedesc)[2].id = 0xfadefeed;
624    (*jzfb->framedesc)[0].cmd = (*jzfb->framedesc)[2].cmd =
625            jzfb->blackline_size / 4;
626    (*jzfb->framedesc)[1].addr = jzfb->vidmem_phys;
627    (*jzfb->framedesc)[1].id = 0xdeafbead;
628    (*jzfb->framedesc)[1].cmd = (max_framesize / 4)
629            | JZ_LCD_CMD_EOF_IRQ | JZ_LCD_CMD_SOF_IRQ;
630
631    return 0;
632
633err_free_blackline:
634    dma_free_coherent(&jzfb->pdev->dev, jzfb->blackline_size,
635                jzfb->blackline, jzfb->blackline_phys);
636err_free_framedesc:
637    dma_free_coherent(&jzfb->pdev->dev, sizeof(*jzfb->framedesc),
638                jzfb->framedesc, jzfb->framedesc_phys);
639    return -ENOMEM;
640}
641
642static void jzfb_free_devmem(struct jzfb *jzfb)
643{
644    dma_free_coherent(&jzfb->pdev->dev, jzfb->vidmem_size,
645                jzfb->vidmem, jzfb->vidmem_phys);
646    dma_free_coherent(&jzfb->pdev->dev, jzfb->blackline_size,
647                jzfb->blackline, jzfb->blackline_phys);
648    dma_free_coherent(&jzfb->pdev->dev, sizeof(*jzfb->framedesc),
649                jzfb->framedesc, jzfb->framedesc_phys);
650}
651
652static int jzfb_tv_out(struct jzfb *jzfb, unsigned int mode)
653{
654    int blank = jzfb->is_enabled ? FB_BLANK_UNBLANK : FB_BLANK_POWERDOWN;
655    struct fb_event event = {
656        .info = jzfb->fb,
657        .data = &blank,
658    };
659
660    printk("A320 TV out: %d\n", mode);
661    if (mode > FB_A320TV_LAST)
662        return -EINVAL;
663    if (mode == jzfb->tv_out)
664        return 0;
665
666    if (mode != FB_A320TV_OFF) {
667        cancel_delayed_work_sync(&jzfb->refresh_work);
668        /* Abort any DMA transfer that might be in progress and
669           allow direct writes to the panel. */
670        jzfb_disable_dma(jzfb);
671        jzfb->panel->disable(jzfb);
672        complete_all(&jzfb->dma_completion);
673
674        /* set up LCD controller for TV output */
675
676        writel(JZ_LCD_CFG_HSYNC_ACTIVE_LOW |
677               JZ_LCD_CFG_VSYNC_ACTIVE_LOW,
678               jzfb->base + JZ_REG_LCD_CFG);
679
680        /* V-Sync pulse end position */
681        writel(10, jzfb->base + JZ_REG_LCD_VSYNC);
682
683        if (mode == FB_A320TV_PAL50) {
684            /* PAL 50 Hz */
685            /* H-Sync pulse start position */
686            writel(0x0000007d, jzfb->base + JZ_REG_LCD_HSYNC);
687            /* virtual area size */
688            writel(0x036c0112, jzfb->base + JZ_REG_LCD_VAT);
689            /* horizontal start/end point */
690            writel(0x02240364, jzfb->base + JZ_REG_LCD_DAH);
691            /* vertical start/end point */
692            writel(0x001a010c, jzfb->base + JZ_REG_LCD_DAV);
693        } else {
694            /* NTSC and PAL 60 Hz */
695            writel(0x0000003c, jzfb->base + JZ_REG_LCD_HSYNC);
696            writel(0x02e00110, jzfb->base + JZ_REG_LCD_VAT);
697            writel(0x019902d9, jzfb->base + JZ_REG_LCD_DAH);
698            writel(0x001c010e, jzfb->base + JZ_REG_LCD_DAV);
699        }
700        writel(0, jzfb->base + JZ_REG_LCD_PS);
701        writel(0, jzfb->base + JZ_REG_LCD_CLS);
702        writel(0, jzfb->base + JZ_REG_LCD_SPL);
703        writel(0, jzfb->base + JZ_REG_LCD_REV);
704        /* reset status register */
705        writel(0, jzfb->base + JZ_REG_LCD_STATE);
706
707        /* tell LCDC about the frame descriptor address */
708        writel(jzfb->framedesc_phys, jzfb->base + JZ_REG_LCD_DA0);
709
710        writel(JZ_LCD_CTRL_BURST_16 | JZ_LCD_CTRL_ENABLE |
711                    JZ_LCD_CTRL_BPP_15_16 |
712                    JZ_LCD_CTRL_EOF_IRQ | JZ_LCD_CTRL_SOF_IRQ,
713                    jzfb->base + JZ_REG_LCD_CTRL);
714    } else {
715        /* disable EOF/SOF interrupts */
716        unsigned long ctrl = readl(jzfb->base + JZ_REG_LCD_CTRL);
717        ctrl &= ~(JZ_LCD_CTRL_EOF_IRQ | JZ_LCD_CTRL_SOF_IRQ);
718        writel(ctrl, jzfb->base + JZ_REG_LCD_CTRL);
719
720        /* disable LCD controller and re-enable SLCD */
721        writel(JZ_LCD_CFG_SLCD, jzfb->base + JZ_REG_LCD_CFG);
722        jzfb->panel->enable(jzfb);
723
724        jzfb->refresh_on_pan = 0;
725        complete_all(&jzfb->dma_completion);
726        schedule_delayed_work(&jzfb->refresh_work, 0);
727    }
728
729    /* reaffirm the current blanking state, to trigger a backlight update */
730    console_lock();
731    fb_notifier_call_chain(FB_EVENT_BLANK, &event);
732    console_unlock();
733    jzfb->tv_out = mode;
734    return 0;
735}
736
737static ssize_t jzfb_tv_out_show(struct device *dev, struct device_attribute *attr,
738            char *buf)
739{
740    struct jzfb *jzfb = dev_get_drvdata(dev);
741
742    if (jzfb->tv_out > FB_A320TV_LAST) {
743        dev_err(dev, "Unknown norm for TV-out\n");
744        return -1;
745    }
746
747    return sprintf(buf, "%s\n", jzfb_tv_out_norm[jzfb->tv_out]);
748}
749
750static ssize_t jzfb_tv_out_store(struct device *dev, struct device_attribute *attr,
751            const char *buf, size_t n)
752{
753    size_t i;
754    struct jzfb *jzfb = dev_get_drvdata(dev);
755
756    for (i = 0; i <= FB_A320TV_LAST; i++) {
757        if (sysfs_streq(jzfb_tv_out_norm[i], buf)) {
758            jzfb_tv_out(jzfb, i);
759            return n;
760        }
761    }
762    return -EINVAL;
763}
764
765static DEVICE_ATTR(tv_out, 0644, jzfb_tv_out_show, jzfb_tv_out_store);
766
767static ssize_t jzfb_vsync_show(struct device *dev, struct device_attribute *attr,
768            char *buf)
769{
770    struct jzfb *jzfb = dev_get_drvdata(dev);
771    return sprintf(buf, "%u\n", jzfb->tv_out_vsync);
772}
773
774static ssize_t jzfb_vsync_store(struct device *dev, struct device_attribute *attr,
775            const char *buf, size_t n)
776{
777    struct jzfb *jzfb = dev_get_drvdata(dev);
778    unsigned int vsync;
779
780    if (sscanf(buf, "%u", &vsync) < 1)
781        return -EINVAL;
782
783    jzfb->tv_out_vsync = vsync;
784    return n;
785}
786
787static DEVICE_ATTR(tv_out_vsync, 0644, jzfb_vsync_show, jzfb_vsync_store);
788
789static ssize_t jzfb_panel_show(struct device *dev, struct device_attribute *attr,
790            char *buf)
791{
792    struct jzfb *jzfb = dev_get_drvdata(dev);
793    return sprintf(buf, "%s\n", jzfb->panel->name);
794}
795
796static ssize_t jzfb_panel_store(struct device *dev, struct device_attribute *attr,
797            const char *buf, size_t n)
798{
799    struct jzfb *jzfb = dev_get_drvdata(dev);
800    const struct jz_slcd_panel *panel = jz_slcd_panel_from_name(buf);
801
802    if (!panel) {
803        dev_err(dev, "Unknown SLCD panel: %s\n", buf);
804        return -EINVAL;
805    }
806
807    if (panel != jzfb->panel) {
808        jzfb->panel->disable(jzfb);
809        jzfb->panel->exit(jzfb);
810        jzfb->panel = panel;
811        panel->init(jzfb);
812        panel->enable(jzfb);
813    }
814    return n;
815}
816
817static DEVICE_ATTR(panel, 0644, jzfb_panel_show, jzfb_panel_store);
818
819static struct fb_ops jzfb_ops = {
820    .owner = THIS_MODULE,
821    .fb_check_var = jzfb_check_var,
822    .fb_set_par = jzfb_set_par,
823    .fb_setcolreg = jzfb_setcolreg,
824    .fb_blank = jzfb_blank,
825    .fb_pan_display = jzfb_pan_display,
826    .fb_fillrect = sys_fillrect,
827    .fb_copyarea = sys_copyarea,
828    .fb_imageblit = sys_imageblit,
829    .fb_mmap = jzfb_mmap,
830};
831
832static irqreturn_t jz4740_lcd_irq(int irq, void *dev_id)
833{
834    struct jzfb *jzfb = dev_id;
835    unsigned long state = readl(jzfb->base + JZ_REG_LCD_STATE);
836
837    if (state & JZ_LCD_STATE_SOF) {
838        INIT_COMPLETION(jzfb->dma_completion);
839        state &= ~JZ_LCD_STATE_SOF;
840    } else {
841        complete_all(&jzfb->dma_completion);
842        state &= ~JZ_LCD_STATE_EOF;
843    }
844
845    /* Acknowledge the interrupt */
846    writel(state, jzfb->base + JZ_REG_LCD_STATE);
847    return IRQ_HANDLED;
848}
849
850static int __devinit jzfb_probe(struct platform_device *pdev)
851{
852    int ret;
853    struct jzfb *jzfb;
854    struct fb_info *fb;
855    struct jz4740_fb_platform_data *pdata = pdev->dev.platform_data;
856    struct resource *mem;
857
858    if (!pdata) {
859        dev_err(&pdev->dev, "Missing platform data\n");
860        return -ENOENT;
861    }
862
863    mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
864
865    if (!mem) {
866        dev_err(&pdev->dev, "Failed to get register memory resource\n");
867        return -ENOENT;
868    }
869
870    mem = request_mem_region(mem->start, resource_size(mem), pdev->name);
871
872    if (!mem) {
873        dev_err(&pdev->dev, "Failed to request register memory region\n");
874        return -EBUSY;
875    }
876
877    fb = framebuffer_alloc(sizeof(struct jzfb), &pdev->dev);
878
879    if (!fb) {
880        dev_err(&pdev->dev, "Failed to allocate framebuffer device\n");
881        ret = -ENOMEM;
882        goto err_release_mem_region;
883    }
884
885    fb->fbops = &jzfb_ops;
886    fb->flags = FBINFO_DEFAULT;
887
888    jzfb = fb->par;
889    jzfb->pdev = pdev;
890    jzfb->pdata = pdata;
891    jzfb->mem = mem;
892
893    jzfb->tv_out = FB_A320TV_OFF;
894    jzfb->tv_out_vsync = 1;
895    jzfb->refresh_on_pan = 0;
896    init_completion(&jzfb->dma_completion);
897    complete_all(&jzfb->dma_completion);
898
899    jzfb->dma = jz4740_dma_request(&pdev->dev, dev_name(&pdev->dev), 0);
900    if (!jzfb->dma) {
901        dev_err(&pdev->dev, "Failed to get DMA channel\n");
902        ret = -EBUSY;
903        goto err_framebuffer_release;
904    }
905    jz4740_dma_configure(jzfb->dma, &jzfb_slcd_dma_config);
906    jz4740_dma_set_complete_cb(jzfb->dma, &jzfb_refresh_work_complete);
907
908    jzfb->ldclk = clk_get(&pdev->dev, "lcd");
909    if (IS_ERR(jzfb->ldclk)) {
910        ret = PTR_ERR(jzfb->ldclk);
911        dev_err(&pdev->dev, "Failed to get lcd clock: %d\n", ret);
912        goto err_free_dma;
913    }
914
915    jzfb->lpclk = clk_get(&pdev->dev, "lcd_pclk");
916    if (IS_ERR(jzfb->lpclk)) {
917        ret = PTR_ERR(jzfb->lpclk);
918        dev_err(&pdev->dev, "Failed to get lcd pixel clock: %d\n", ret);
919        goto err_put_ldclk;
920    }
921
922    jzfb->base = ioremap(mem->start, resource_size(mem));
923
924    if (!jzfb->base) {
925        dev_err(&pdev->dev, "Failed to ioremap register memory region\n");
926        ret = -EBUSY;
927        goto err_put_lpclk;
928    }
929
930    platform_set_drvdata(pdev, jzfb);
931
932    fb_videomode_to_modelist(pdata->modes, pdata->num_modes,
933                 &fb->modelist);
934    fb->mode = pdata->modes;
935
936    fb_videomode_to_var(&fb->var, fb->mode);
937    fb->var.bits_per_pixel = pdata->bpp;
938    jzfb_check_var(&fb->var, fb);
939
940    ret = jzfb_alloc_devmem(jzfb);
941    if (ret) {
942        dev_err(&pdev->dev, "Failed to allocate video memory\n");
943        goto err_iounmap;
944    }
945
946    fb->fix = jzfb_fix;
947    fb->fix.line_length = fb->var.bits_per_pixel * fb->var.xres / 8;
948    fb->fix.mmio_start = mem->start;
949    fb->fix.mmio_len = resource_size(mem);
950    fb->fix.smem_start = jzfb->vidmem_phys;
951    fb->fix.smem_len = fb->fix.line_length * fb->var.yres_virtual;
952    fb->screen_base = jzfb->vidmem;
953    fb->pseudo_palette = jzfb->pseudo_palette;
954
955    fb_alloc_cmap(&fb->cmap, 256, 0);
956
957    mutex_init(&jzfb->lock);
958
959    clk_enable(jzfb->ldclk);
960    jzfb->is_enabled = 1;
961
962    writel(JZ_LCD_CFG_SLCD, jzfb->base + JZ_REG_LCD_CFG);
963    writeb(0, jzfb->base + JZ_REG_SLCD_CTRL);
964
965    jzfb_set_par(fb);
966
967    jz_gpio_bulk_request(jz_slcd_ctrl_pins, jzfb_num_ctrl_pins(jzfb));
968    if (jzfb->pdata->lcd_type & (1 << 6)) {
969        /* serial */
970        jz_gpio_bulk_request(&jz_slcd_data_pins[15], 1);
971    } else {
972        /* parallel */
973        jz_gpio_bulk_request(jz_slcd_data_pins,
974                     jzfb_num_data_pins(jzfb));
975    }
976
977    ret = request_irq(JZ4740_IRQ_LCD, jz4740_lcd_irq, 0, "LCD", jzfb);
978    if (ret) {
979        dev_err(&pdev->dev, "Failed to request IRQ\n");
980        goto err_free_devmem;
981    }
982
983    jzfb->panel = jz_slcd_panels_probe(jzfb);
984    if (!jzfb->panel) {
985        dev_err(&pdev->dev, "Failed to find panel driver\n");
986        ret = -ENOENT;
987        goto err_free_irq;
988    }
989    jzfb_disable_dma(jzfb);
990    jzfb->panel->init(jzfb);
991
992    jzfb->panel->enable(jzfb);
993
994    ret = register_framebuffer(fb);
995    if (ret) {
996        dev_err(&pdev->dev, "Failed to register framebuffer: %d\n", ret);
997        goto err_free_panel;
998    }
999
1000    jzfb->fb = fb;
1001    fb_prepare_logo(jzfb->fb, 0);
1002    fb_show_logo(jzfb->fb, 0);
1003
1004    INIT_DELAYED_WORK(&jzfb->refresh_work, jzfb_refresh_work);
1005    schedule_delayed_work(&jzfb->refresh_work, 0);
1006
1007    ret = device_create_file(&pdev->dev, &dev_attr_panel);
1008    if (ret)
1009        goto err_cancel_work;
1010
1011    ret = device_create_file(&pdev->dev, &dev_attr_tv_out);
1012    if (ret)
1013        goto err_remove_file_panel;
1014
1015    ret = device_create_file(&pdev->dev, &dev_attr_tv_out_vsync);
1016    if (!ret)
1017        return 0;
1018
1019    device_remove_file(&pdev->dev, &dev_attr_tv_out);
1020err_remove_file_panel:
1021    device_remove_file(&pdev->dev, &dev_attr_panel);
1022err_cancel_work:
1023    cancel_delayed_work_sync(&jzfb->refresh_work);
1024err_free_panel:
1025    jzfb->panel->exit(jzfb);
1026err_free_irq:
1027    free_irq(JZ4740_IRQ_LCD, jzfb);
1028err_free_devmem:
1029    jzfb_free_gpio_pins(jzfb);
1030
1031    fb_dealloc_cmap(&fb->cmap);
1032    jzfb_free_devmem(jzfb);
1033err_iounmap:
1034    iounmap(jzfb->base);
1035err_put_lpclk:
1036    clk_put(jzfb->lpclk);
1037err_put_ldclk:
1038    clk_put(jzfb->ldclk);
1039err_free_dma:
1040    jz4740_dma_free(jzfb->dma);
1041err_framebuffer_release:
1042    framebuffer_release(fb);
1043err_release_mem_region:
1044    release_mem_region(mem->start, resource_size(mem));
1045    return ret;
1046}
1047
1048static int __devexit jzfb_remove(struct platform_device *pdev)
1049{
1050    struct jzfb *jzfb = platform_get_drvdata(pdev);
1051
1052    device_remove_file(&pdev->dev, &dev_attr_tv_out_vsync);
1053    device_remove_file(&pdev->dev, &dev_attr_tv_out);
1054    device_remove_file(&pdev->dev, &dev_attr_panel);
1055    jzfb_blank(FB_BLANK_POWERDOWN, jzfb->fb);
1056
1057    free_irq(JZ4740_IRQ_LCD, jzfb);
1058
1059    /* Blanking will prevent future refreshes from behind scheduled.
1060       Now wait for a possible refresh in progress to finish. */
1061    cancel_delayed_work_sync(&jzfb->refresh_work);
1062
1063    jzfb->panel->exit(jzfb);
1064
1065    jzfb_free_gpio_pins(jzfb);
1066
1067    jz4740_dma_free(jzfb->dma);
1068
1069    iounmap(jzfb->base);
1070    release_mem_region(jzfb->mem->start, resource_size(jzfb->mem));
1071
1072    fb_dealloc_cmap(&jzfb->fb->cmap);
1073    jzfb_free_devmem(jzfb);
1074
1075    platform_set_drvdata(pdev, NULL);
1076
1077    clk_put(jzfb->lpclk);
1078    clk_put(jzfb->ldclk);
1079
1080    framebuffer_release(jzfb->fb);
1081
1082    return 0;
1083}
1084
1085#ifdef CONFIG_PM
1086
1087static int jzfb_suspend(struct device *dev)
1088{
1089    struct jzfb *jzfb = dev_get_drvdata(dev);
1090
1091    console_lock();
1092    fb_set_suspend(jzfb->fb, 1);
1093    console_unlock();
1094
1095    mutex_lock(&jzfb->lock);
1096    if (jzfb->is_enabled)
1097        jzfb_disable(jzfb);
1098    mutex_unlock(&jzfb->lock);
1099
1100    return 0;
1101}
1102
1103static int jzfb_resume(struct device *dev)
1104{
1105    struct jzfb *jzfb = dev_get_drvdata(dev);
1106
1107    mutex_lock(&jzfb->lock);
1108    if (jzfb->is_enabled)
1109        jzfb_enable(jzfb);
1110    mutex_unlock(&jzfb->lock);
1111
1112    console_lock();
1113    fb_set_suspend(jzfb->fb, 0);
1114    console_unlock();
1115
1116    return 0;
1117}
1118
1119static SIMPLE_DEV_PM_OPS(jzfb_pm_ops, jzfb_suspend, jzfb_resume);
1120
1121#define JZFB_PM_OPS (&jzfb_pm_ops)
1122
1123#else
1124#define JZFB_PM_OPS NULL
1125#endif
1126
1127static struct platform_driver jzfb_driver = {
1128    .probe = jzfb_probe,
1129    .remove = __devexit_p(jzfb_remove),
1130    .driver = {
1131        .name = "jz4740-fb",
1132        .pm = JZFB_PM_OPS,
1133    },
1134};
1135
1136static int __init jzfb_init(void)
1137{
1138    return platform_driver_register(&jzfb_driver);
1139}
1140module_init(jzfb_init);
1141
1142static void __exit jzfb_exit(void)
1143{
1144    platform_driver_unregister(&jzfb_driver);
1145}
1146module_exit(jzfb_exit);
1147
1148MODULE_LICENSE("GPL");
1149MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>, Maarten ter Huurne <maarten@treewalker.org>");
1150MODULE_DESCRIPTION("JZ4740 SoC SLCD framebuffer driver");
1151MODULE_ALIAS("platform:jz4740-fb");
drivers/video/jz4740_slcd_panels.c
1/*
2 * linux/drivers/video/jz4740_slcd_panels.c
3 * -- LCD panel definitions for Ingenic On-Chip SLCD frame buffer device
4 *
5 * Copyright (C) 2005-2007, Ingenic Semiconductor Inc.
6 * Copyright (C) 2009, Ignacio Garcia Perez <iggarpe@gmail.com>
7 * Copyright (C) 2010, Maarten ter Huurne <maarten@treewalker.org>
8 * Copyright (C) 2011, ChinaChip
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License version 2 as
12 * published by the Free Software Foundation.
13 *
14 */
15
16#include <asm/io.h>
17#include <asm/mach-jz4740/gpio.h>
18#include <asm/mach-jz4740/jz4740_fb.h>
19#include <linux/delay.h>
20#include <linux/gpio.h>
21#include <linux/kernel.h>
22#include <linux/moduleparam.h>
23#include <linux/platform_device.h>
24
25#include "jz4740_slcd.h"
26
27static char *default_slcd_panel;
28#ifdef CONFIG_JZ_SLCD_ILI9338
29static unsigned int default_slcd_rgb[3] = { 100, 100, 100, };
30#endif
31
32/* Send a command without data. */
33static void send_panel_command(struct jzfb *jzfb, u32 cmd) {
34    u16 slcd_cfg = readw(jzfb->base + JZ_REG_SLCD_CFG);
35    switch (slcd_cfg & SLCD_CFG_CWIDTH_MASK) {
36    case SLCD_CFG_CWIDTH_8BIT:
37        while (readb(jzfb->base + JZ_REG_SLCD_STATE) & SLCD_STATE_BUSY);
38        writel(SLCD_DATA_RS_COMMAND | ((cmd&0xff00) >> 8), jzfb->base + JZ_REG_SLCD_DATA);
39        while (readb(jzfb->base + JZ_REG_SLCD_STATE) & SLCD_STATE_BUSY);
40        writel(SLCD_DATA_RS_COMMAND | ((cmd&0xff) >> 0), jzfb->base + JZ_REG_SLCD_DATA);
41        break;
42    case SLCD_CFG_CWIDTH_16BIT:
43        while (readb(jzfb->base + JZ_REG_SLCD_STATE) & SLCD_STATE_BUSY);
44        writel(SLCD_DATA_RS_COMMAND | (cmd&0xffff), jzfb->base + JZ_REG_SLCD_DATA);
45        break;
46    case SLCD_CFG_CWIDTH_18BIT:
47        while (readb(jzfb->base + JZ_REG_SLCD_STATE) & SLCD_STATE_BUSY);
48        writel(SLCD_DATA_RS_COMMAND | ((cmd&0xff00) << 2) | ((cmd&0xff) << 1), jzfb->base + JZ_REG_SLCD_DATA);
49        break;
50    default:
51        break;
52    }
53}
54
55/* Send data without command. */
56static void send_panel_data(struct jzfb *jzfb, u32 data)
57{
58    u16 slcd_cfg = readw(jzfb->base + JZ_REG_SLCD_CFG);
59    switch (slcd_cfg & SLCD_CFG_DWIDTH_MASK) {
60    case SLCD_CFG_DWIDTH_18:
61        while (readb(jzfb->base + JZ_REG_SLCD_STATE) & SLCD_STATE_BUSY);
62        data = ((data & 0xff) << 1) | ((data & 0xff00) << 2);
63        writel(SLCD_DATA_RS_DATA | ((data<<6)&0xfc0000)|((data<<4)&0xfc00) | ((data<<2)&0xfc), jzfb->base + JZ_REG_SLCD_DATA);
64        break;
65    case SLCD_CFG_DWIDTH_16:
66        while (readb(jzfb->base + JZ_REG_SLCD_STATE) & SLCD_STATE_BUSY);
67        writel(SLCD_DATA_RS_DATA | (data&0xffff), jzfb->base + JZ_REG_SLCD_DATA);
68        break;
69    case SLCD_CFG_DWIDTH_9_x2:
70        data = ((data & 0xff) << 1) | ((data & 0xff00) << 2);
71        data = ((data << 6) & 0xfc0000) | ((data << 4) & 0xfc00) | ((data << 2) & 0xfc);
72        while (readb(jzfb->base + JZ_REG_SLCD_STATE) & SLCD_STATE_BUSY);
73        writel(SLCD_DATA_RS_DATA | data, jzfb->base + JZ_REG_SLCD_DATA);
74        break;
75    default:
76        while (readb(jzfb->base + JZ_REG_SLCD_STATE) & SLCD_STATE_BUSY);
77        writel(SLCD_DATA_RS_DATA | (data&0xffff), jzfb->base + JZ_REG_SLCD_DATA);
78        break;
79    }
80}
81
82/* Send command and data. */
83static void set_panel_reg(struct jzfb *jzfb, u32 cmd, u32 data)
84{
85    send_panel_command(jzfb, cmd);
86    send_panel_data(jzfb, data);
87}
88
89#ifdef CONFIG_JZ_SLCD_ILI9325
90
91// TODO(MtH): GPIO assignments belong in the board definition, since two
92// boards using the same panel controller could still use different
93// GPIO assignments.
94// TODO(MtH): CS mismatch: B17 (A320) vs C20 (standard).
95#define ILI9325_GPIO_CS_N JZ_GPIO_PORTB(17) /* Chip select */
96#define ILI9325_GPIO_RESET_N JZ_GPIO_PORTB(18) /* LCD reset */
97
98static void ili9325_enable(struct jzfb *jzfb)
99{
100    /* RESET pulse */
101    gpio_set_value(ILI9325_GPIO_RESET_N, 0);
102    msleep(10);
103    gpio_set_value(ILI9325_GPIO_RESET_N, 1);
104    msleep(50);
105
106    /* Enable chip select */
107    gpio_set_value(ILI9325_GPIO_CS_N, 0);
108
109    /* Black magic */
110    set_panel_reg(jzfb, 0xE3, 0x3008);
111    set_panel_reg(jzfb, 0xE7, 0x0012);
112    set_panel_reg(jzfb, 0xEF, 0x1231);
113    set_panel_reg(jzfb, 0x01, 0x0100);
114    set_panel_reg(jzfb, 0x02, 0x0700);
115    set_panel_reg(jzfb, 0x03, 0x1098);
116    set_panel_reg(jzfb, 0x04, 0x0000);
117    set_panel_reg(jzfb, 0x08, 0x0207);
118    set_panel_reg(jzfb, 0x09, 0x0000);
119    set_panel_reg(jzfb, 0x0A, 0x0000);
120    set_panel_reg(jzfb, 0x0C, 0x0000);
121    set_panel_reg(jzfb, 0x0D, 0x0000);
122    set_panel_reg(jzfb, 0x0F, 0x0000);
123    set_panel_reg(jzfb, 0x10, 0x0000);
124    set_panel_reg(jzfb, 0x11, 0x0007);
125    set_panel_reg(jzfb, 0x12, 0x0000);
126    set_panel_reg(jzfb, 0x13, 0x0000);
127    msleep(200);
128    set_panel_reg(jzfb, 0x10, 0x1290);
129    set_panel_reg(jzfb, 0x11, 0x0227);
130    msleep(50);
131    set_panel_reg(jzfb, 0x12, 0x001B);
132    msleep(50);
133    set_panel_reg(jzfb, 0x13, 0x0500);
134    set_panel_reg(jzfb, 0x29, 0x000C);
135    set_panel_reg(jzfb, 0x2B, 0x000D);
136    msleep(50);
137    set_panel_reg(jzfb, 0x20, 0x0000);
138    set_panel_reg(jzfb, 0x21, 0x0000);
139    set_panel_reg(jzfb, 0x30, 0x0000);
140    set_panel_reg(jzfb, 0x31, 0x0204);
141    set_panel_reg(jzfb, 0x32, 0x0200);
142    set_panel_reg(jzfb, 0x35, 0x0007);
143    set_panel_reg(jzfb, 0x36, 0x1404);
144    set_panel_reg(jzfb, 0x37, 0x0705);
145    set_panel_reg(jzfb, 0x38, 0x0305);
146    set_panel_reg(jzfb, 0x39, 0x0707);
147    set_panel_reg(jzfb, 0x3C, 0x0701);
148    set_panel_reg(jzfb, 0x3D, 0x000E);
149    set_panel_reg(jzfb, 0x50, 0x0000);
150    set_panel_reg(jzfb, 0x51, 0x00EF);
151    set_panel_reg(jzfb, 0x52, 0x0000);
152    set_panel_reg(jzfb, 0x53, 0x013F);
153    set_panel_reg(jzfb, 0x60, 0xA700);
154    set_panel_reg(jzfb, 0x61, 0x0001);
155    set_panel_reg(jzfb, 0x6A, 0x0000);
156    set_panel_reg(jzfb, 0x80, 0x0000);
157    set_panel_reg(jzfb, 0x81, 0x0000);
158    set_panel_reg(jzfb, 0x82, 0x0000);
159    set_panel_reg(jzfb, 0x83, 0x0000);
160    set_panel_reg(jzfb, 0x84, 0x0000);
161    set_panel_reg(jzfb, 0x85, 0x0000);
162    set_panel_reg(jzfb, 0x90, 0x0010);
163    set_panel_reg(jzfb, 0x92, 0x0600);
164    msleep(50);
165    set_panel_reg(jzfb, 0x07, 0x0133);
166    msleep(50);
167    send_panel_command(jzfb, 0x22);
168}
169
170/* TODO(IGP): make sure LCD power consumption is low in these conditions */
171static void ili9325_disable(struct jzfb *jzfb)
172{
173    /* Keep chip select disabled */
174    gpio_set_value(ILI9325_GPIO_CS_N, 1);
175    /* Keep RESET active */
176    gpio_set_value(ILI9325_GPIO_RESET_N, 0);
177}
178
179static int ili9325_init(struct jzfb *jzfb)
180{
181    struct device *dev = &jzfb->pdev->dev;
182    int ret;
183
184    ret = gpio_request(ILI9325_GPIO_CS_N, dev_name(dev));
185    if (ret)
186        goto err_cs;
187    gpio_direction_output(ILI9325_GPIO_CS_N, 1);
188
189    ret = gpio_request(ILI9325_GPIO_RESET_N, dev_name(dev));
190    if (ret)
191        goto err_reset;
192    gpio_direction_output(ILI9325_GPIO_RESET_N, 0);
193
194    msleep(100);
195    return 0;
196
197err_reset:
198    gpio_free(ILI9325_GPIO_CS_N);
199err_cs:
200    dev_err(dev, "Could not reserve GPIO pins for ILI9325 panel driver\n");
201    return ret;
202}
203
204static void ili9325_exit(struct jzfb *jzfb)
205{
206    gpio_free(ILI9325_GPIO_CS_N);
207    gpio_free(ILI9325_GPIO_RESET_N);
208}
209
210#endif
211
212#ifdef CONFIG_JZ_SLCD_ILI9331
213
214#define ILI9331_GPIO_CS_N JZ_GPIO_PORTB(17) /* Chip select */
215#define ILI9331_GPIO_RESET_N JZ_GPIO_PORTB(18) /* LCD reset */
216
217static void ili9331_enable(struct jzfb *jzfb)
218{
219    /* RESET pulse */
220    gpio_set_value(ILI9331_GPIO_RESET_N, 0);
221    msleep(10);
222    gpio_set_value(ILI9331_GPIO_RESET_N, 1);
223    msleep(50);
224
225    /* Enable chip select */
226    gpio_set_value(ILI9331_GPIO_CS_N, 0);
227
228    /* Black magic */
229    set_panel_reg(jzfb, 0xE7, 0x1014);
230    set_panel_reg(jzfb, 0x01, 0x0000);
231    set_panel_reg(jzfb, 0x02, 0x0200);
232    set_panel_reg(jzfb, 0x03, 0x1048);
233    set_panel_reg(jzfb, 0x08, 0x0202);
234    set_panel_reg(jzfb, 0x09, 0x0000);
235    set_panel_reg(jzfb, 0x0A, 0x0000);
236    set_panel_reg(jzfb, 0x0C, 0x0000);
237    set_panel_reg(jzfb, 0x0D, 0x0000);
238    set_panel_reg(jzfb, 0x0F, 0x0000);
239    set_panel_reg(jzfb, 0x10, 0x0000);
240    set_panel_reg(jzfb, 0x11, 0x0007);
241    set_panel_reg(jzfb, 0x12, 0x0000);
242    set_panel_reg(jzfb, 0x13, 0x0000);
243    msleep(100);
244    set_panel_reg(jzfb, 0x10, 0x1690);
245    set_panel_reg(jzfb, 0x11, 0x0224);
246    msleep(50);
247    set_panel_reg(jzfb, 0x12, 0x001F);
248    msleep(50);
249    set_panel_reg(jzfb, 0x13, 0x0500);
250    set_panel_reg(jzfb, 0x29, 0x000C);
251    set_panel_reg(jzfb, 0x2B, 0x000D);
252    msleep(50);
253    set_panel_reg(jzfb, 0x30, 0x0000);
254    set_panel_reg(jzfb, 0x31, 0x0106);
255    set_panel_reg(jzfb, 0x32, 0x0000);
256    set_panel_reg(jzfb, 0x35, 0x0204);
257    set_panel_reg(jzfb, 0x36, 0x160A);
258    set_panel_reg(jzfb, 0x37, 0x0707);
259    set_panel_reg(jzfb, 0x38, 0x0106);
260    set_panel_reg(jzfb, 0x39, 0x0706);
261    set_panel_reg(jzfb, 0x3C, 0x0402);
262    set_panel_reg(jzfb, 0x3D, 0x0C0F);
263    set_panel_reg(jzfb, 0x50, 0x0000);
264    set_panel_reg(jzfb, 0x51, 0x00EF);
265    set_panel_reg(jzfb, 0x52, 0x0000);
266    set_panel_reg(jzfb, 0x53, 0x013F);
267    set_panel_reg(jzfb, 0x20, 0x0000);
268    set_panel_reg(jzfb, 0x21, 0x0000);
269    set_panel_reg(jzfb, 0x60, 0x2700);
270    set_panel_reg(jzfb, 0x61, 0x0001);
271    set_panel_reg(jzfb, 0x6A, 0x0000);
272    set_panel_reg(jzfb, 0x80, 0x0000);
273    set_panel_reg(jzfb, 0x81, 0x0000);
274    set_panel_reg(jzfb, 0x82, 0x0000);
275    set_panel_reg(jzfb, 0x83, 0x0000);
276    set_panel_reg(jzfb, 0x84, 0x0000);
277    set_panel_reg(jzfb, 0x85, 0x0000);
278    set_panel_reg(jzfb, 0x20, 0x00EF);
279    set_panel_reg(jzfb, 0x21, 0x0190);
280    set_panel_reg(jzfb, 0x90, 0x0010);
281    set_panel_reg(jzfb, 0x92, 0x0600);
282    set_panel_reg(jzfb, 0x07, 0x0133);
283    send_panel_command(jzfb, 0x22);
284}
285
286/* TODO(IGP): make sure LCD power consumption is low in these conditions */
287static void ili9331_disable(struct jzfb *jzfb)
288{
289    /* Keep chip select disabled */
290    gpio_set_value(ILI9331_GPIO_CS_N, 1);
291    /* Keep RESET active */
292    gpio_set_value(ILI9331_GPIO_RESET_N, 0);
293}
294
295static int ili9331_init(struct jzfb *jzfb)
296{
297    struct device *dev = &jzfb->pdev->dev;
298    int ret;
299
300    ret = gpio_request(ILI9331_GPIO_CS_N, dev_name(dev));
301    if (ret)
302        goto err_cs;
303    gpio_direction_output(ILI9331_GPIO_CS_N, 1);
304
305    ret = gpio_request(ILI9331_GPIO_RESET_N, dev_name(dev));
306    if (ret)
307        goto err_reset;
308    gpio_direction_output(ILI9331_GPIO_RESET_N, 0);
309
310    msleep(100);
311    return 0;
312
313err_reset:
314    gpio_free(ILI9331_GPIO_CS_N);
315err_cs:
316    dev_err(dev, "Could not reserve GPIO pins for ILI9331 panel driver\n");
317    return ret;
318}
319
320static void ili9331_exit(struct jzfb *jzfb)
321{
322    gpio_free(ILI9331_GPIO_CS_N);
323    gpio_free(ILI9331_GPIO_RESET_N);
324}
325
326#endif
327
328#ifdef CONFIG_JZ_SLCD_ILI9338
329
330static void ili9338_set_color_table(struct jzfb *jzfb)
331{
332    unsigned int c;
333    struct device *dev = &jzfb->pdev->dev;
334
335    /* Set up a custom color lookup table.
336     * This helps to fix the 'blueish' display on some devices. */
337    send_panel_command(jzfb, 0x2d);
338
339    for (c = 0; c < 3; c++) {
340        unsigned int i, n, v, s;
341        n = c == 1 ? 64 /* 6 bits G */ : 32 /* 5 bits R/B */;
342        s = jzfb->rgb[c] * (((63 << 24) - 1) / (100 * (n - 1)));
343        v = 0;
344        for (i = 0; i < n; i++, v += s)
345            send_panel_data(jzfb, (v >> 24) + ((v >> 23) & 1));
346    }
347
348    dev_info(dev, "ILI9338 color table initialized with R=%u G=%u B=%u\n",
349                jzfb->rgb[0], jzfb->rgb[1], jzfb->rgb[2]);
350}
351
352module_param_array_named(rgb, default_slcd_rgb, uint, NULL, 0);
353MODULE_PARM_DESC(rgb, "comma-separated list of three values representing the percentage of red, green and blue");
354
355static ssize_t rgb_show(struct device *dev, struct device_attribute *attr,
356            char *buf)
357{
358    struct jzfb *jzfb = dev_get_drvdata(dev);
359    return sprintf(buf, "%u,%u,%u\n", jzfb->rgb[0],
360                jzfb->rgb[1], jzfb->rgb[2]);
361}
362
363static ssize_t rgb_store(struct device *dev, struct device_attribute *attr,
364            const char *buf, size_t n)
365{
366    struct jzfb *jzfb = dev_get_drvdata(dev);
367    unsigned int rgb[3];
368
369    if (sscanf(buf, "%u,%u,%u", &rgb[0], &rgb[1], &rgb[2]) < 3)
370        return -EINVAL;
371
372    if (rgb[0] > 100 || rgb[1] > 100 || rgb[2] > 100)
373        return -EINVAL;
374
375    memcpy(jzfb->rgb, rgb, sizeof(rgb));
376    ili9338_set_color_table(jzfb);
377    return n;
378}
379
380static DEVICE_ATTR(rgb, 0644, rgb_show, rgb_store);
381
382#define ILI9338_GPIO_CS_N JZ_GPIO_PORTB(17) /* Chip select */
383#define ILI9338_GPIO_RESET_N JZ_GPIO_PORTB(18) /* LCD reset */
384
385static void ili9338_enable(struct jzfb *jzfb)
386{
387    /* RESET pulse */
388    gpio_set_value(ILI9338_GPIO_RESET_N, 0);
389    msleep(10);
390    gpio_set_value(ILI9338_GPIO_RESET_N, 1);
391    msleep(50);
392
393    /* Enable chip select */
394    gpio_set_value(ILI9338_GPIO_CS_N, 0);
395
396    /* Black magic */
397    send_panel_command(jzfb, 0x11);
398    msleep(100);
399
400    send_panel_command(jzfb, 0xCB);
401    send_panel_data(jzfb, 0x01);
402
403    send_panel_command(jzfb, 0xC0);
404    send_panel_data(jzfb, 0x26);
405    send_panel_data(jzfb, 0x01);
406    send_panel_command(jzfb, 0xC1);
407    send_panel_data(jzfb, 0x10);
408    send_panel_command(jzfb, 0xC5);
409    send_panel_data(jzfb, 0x10);
410    send_panel_data(jzfb, 0x52);
411
412    send_panel_command(jzfb, 0x26);
413    send_panel_data(jzfb, 0x01);
414    send_panel_command(jzfb, 0xE0);
415    send_panel_data(jzfb, 0x10);
416    send_panel_data(jzfb, 0x10);
417    send_panel_data(jzfb, 0x10);
418    send_panel_data(jzfb, 0x08);
419    send_panel_data(jzfb, 0x0E);
420    send_panel_data(jzfb, 0x06);
421    send_panel_data(jzfb, 0x42);
422    send_panel_data(jzfb, 0x28);
423    send_panel_data(jzfb, 0x36);
424    send_panel_data(jzfb, 0x03);
425    send_panel_data(jzfb, 0x0E);
426    send_panel_data(jzfb, 0x04);
427    send_panel_data(jzfb, 0x13);
428    send_panel_data(jzfb, 0x0E);
429    send_panel_data(jzfb, 0x0C);
430    send_panel_command(jzfb, 0XE1);
431    send_panel_data(jzfb, 0x0C);
432    send_panel_data(jzfb, 0x23);
433    send_panel_data(jzfb, 0x26);
434    send_panel_data(jzfb, 0x04);
435    send_panel_data(jzfb, 0x0C);
436    send_panel_data(jzfb, 0x04);
437    send_panel_data(jzfb, 0x39);
438    send_panel_data(jzfb, 0x24);
439    send_panel_data(jzfb, 0x4B);
440    send_panel_data(jzfb, 0x03);
441    send_panel_data(jzfb, 0x0B);
442    send_panel_data(jzfb, 0x0B);
443    send_panel_data(jzfb, 0x33);
444    send_panel_data(jzfb, 0x37);
445    send_panel_data(jzfb, 0x0F);
446
447    send_panel_command(jzfb, 0x2a);
448    send_panel_data(jzfb, 0x00);
449    send_panel_data(jzfb, 0x00);
450    send_panel_data(jzfb, 0x01);
451    send_panel_data(jzfb, 0x3f);
452
453    send_panel_command(jzfb, 0x2b);
454    send_panel_data(jzfb, 0x00);
455    send_panel_data(jzfb, 0x00);
456    send_panel_data(jzfb, 0x00);
457    send_panel_data(jzfb, 0xef);
458
459    send_panel_command(jzfb, 0x36);
460    send_panel_data(jzfb, 0xe8);
461
462    send_panel_command(jzfb, 0x3A);
463    send_panel_data(jzfb, 0x05);
464
465    ili9338_set_color_table(jzfb);
466
467    send_panel_command(jzfb, 0x29);
468
469    send_panel_command(jzfb, 0x2c);
470}
471
472/* TODO(IGP): make sure LCD power consumption is low in these conditions */
473static void ili9338_disable(struct jzfb *jzfb)
474{
475    /* Keep chip select disabled */
476    gpio_set_value(ILI9338_GPIO_CS_N, 1);
477    /* Keep RESET active */
478    gpio_set_value(ILI9338_GPIO_RESET_N, 0);
479}
480
481static int ili9338_init(struct jzfb *jzfb)
482{
483    struct device *dev = &jzfb->pdev->dev;
484    int ret;
485
486    ret = gpio_request(ILI9338_GPIO_CS_N, dev_name(dev));
487    if (ret)
488        goto err_cs;
489    gpio_direction_output(ILI9338_GPIO_CS_N, 1);
490
491    ret = gpio_request(ILI9338_GPIO_RESET_N, dev_name(dev));
492    if (ret)
493        goto err_reset;
494    gpio_direction_output(ILI9338_GPIO_RESET_N, 0);
495
496    memcpy(jzfb->rgb, default_slcd_rgb, sizeof(default_slcd_rgb));
497    msleep(100);
498
499    ret = device_create_file(dev, &dev_attr_rgb);
500    if (!ret)
501        return 0;
502
503err_reset:
504    gpio_free(ILI9338_GPIO_CS_N);
505err_cs:
506    dev_err(dev, "Could not reserve GPIO pins for ILI9338 panel driver\n");
507    return ret;
508}
509
510static void ili9338_exit(struct jzfb *jzfb)
511{
512    struct device *dev = &jzfb->pdev->dev;
513    device_remove_file(dev, &dev_attr_rgb);
514
515    gpio_free(ILI9338_GPIO_CS_N);
516    gpio_free(ILI9338_GPIO_RESET_N);
517}
518
519#endif
520
521static const struct jz_slcd_panel jz_slcd_panels[] = {
522#ifdef CONFIG_JZ_SLCD_ILI9325
523    {
524        ili9325_init, ili9325_exit,
525        ili9325_enable, ili9325_disable,
526        "ili9325",
527    },
528#endif
529#ifdef CONFIG_JZ_SLCD_ILI9331
530    {
531        ili9331_init, ili9331_exit,
532        ili9331_enable, ili9331_disable,
533        "ili9331",
534    },
535#endif
536#ifdef CONFIG_JZ_SLCD_ILI9338
537    {
538        ili9338_init, ili9338_exit,
539        ili9338_enable, ili9338_disable,
540        "ili9338",
541    },
542#endif
543};
544
545module_param_named(panel, default_slcd_panel, charp, 0);
546MODULE_PARM_DESC(panel, "SLCD panel used on the device");
547
548const struct jz_slcd_panel *jz_slcd_panel_from_name(const char *name)
549{
550    unsigned int i;
551    for (i = 0; i < ARRAY_SIZE(jz_slcd_panels); i++) {
552        if (sysfs_streq(name, jz_slcd_panels[i].name))
553            return &jz_slcd_panels[i];
554    }
555    return NULL;
556}
557
558const struct jz_slcd_panel *jz_slcd_panels_probe(struct jzfb *jzfb)
559{
560    const struct jz_slcd_panel *panel;
561    if (ARRAY_SIZE(jz_slcd_panels) == 0)
562        return NULL;
563
564    panel = &jz_slcd_panels[0];
565
566    if (default_slcd_panel) {
567        panel = jz_slcd_panel_from_name(default_slcd_panel);
568        if (!panel) {
569            struct device *dev = &jzfb->pdev->dev;
570            dev_err(dev, "Unknown SLCD panel: %s\n",
571                        default_slcd_panel);
572        }
573    }
574    return panel;
575}

Archive Download the corresponding diff file



interactive