Date:2011-06-06 05:41:21 (12 years 9 months ago)
Author:Maarten ter Huurne
Commit:0aea73bcf352b359b796cba77b56ab75cabf6f83
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/fbdev/Kconfig (1 diff)
drivers/video/fbdev/Makefile (1 diff)
drivers/video/fbdev/jz4740_fb.c (1 diff)
drivers/video/fbdev/jz4740_lcd.h (1 diff)
drivers/video/fbdev/jz4740_slcd.h (1 diff)
drivers/video/fbdev/jz4740_slcd_fb.c (1 diff)
drivers/video/fbdev/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/fbdev/Kconfig
23942394    help
23952395      Framebuffer support for the JZ4740 SoC.
23962396
2397config FB_JZ4740_SLCD
2398    tristate "JZ4740 Smart LCD framebuffer support"
2399    depends on FB && MACH_JZ4740
2400    select FB_SYS_FILLRECT
2401    select FB_SYS_COPYAREA
2402    select FB_SYS_IMAGEBLIT
2403    help
2404      This is the frame buffer device driver for the JZ4740 Smart LCD controller.
2405      If you say Y here, please say N to 'JZ4740 LCD framebuffer support'.
2406
2407config JZ_SLCD_ILI9325
2408    bool "ILI9325 Smart LCD panel"
2409    depends on FB_JZ4740_SLCD
2410
2411config JZ_SLCD_ILI9331
2412    bool "ILI9331 Smart LCD panel"
2413    depends on FB_JZ4740_SLCD
2414
2415config JZ_SLCD_ILI9338
2416    bool "ILI9338 Smart LCD panel"
2417    depends on FB_JZ4740_SLCD
2418
23972419config FB_MXS
23982420    tristate "MXS LCD framebuffer support"
23992421    depends on FB && ARCH_MXS
drivers/video/fbdev/Makefile
127127obj-$(CONFIG_FB_MSM) += msm/
128128obj-$(CONFIG_FB_NUC900) += nuc900fb.o
129129obj-$(CONFIG_FB_JZ4740) += jz4740_fb.o
130obj-$(CONFIG_FB_JZ4740_SLCD) += jz4740_slcd_fb.o jz4740_slcd_panels.o
130131obj-$(CONFIG_FB_PUV3_UNIGFX) += fb-puv3.o
131132obj-$(CONFIG_FB_HYPERV) += hyperv_fb.o
132133obj-$(CONFIG_FB_OPENCORES) += ocfb.o
drivers/video/fbdev/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/fbdev/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/fbdev/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/fbdev/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/interrupt.h>
29#include <linux/dma-mapping.h>
30
31#include <asm/mach-jz4740/dma.h>
32#include <asm/mach-jz4740/gpio.h>
33#include <asm/mach-jz4740/jz4740_fb.h>
34
35#include "jz4740_lcd.h"
36#include "jz4740_slcd.h"
37
38#define FB_A320TV_OFF 0
39#define FB_A320TV_NTSC 1
40#define FB_A320TV_PAL50 2
41#define FB_A320TV_PAL60 3
42#define FB_A320TV_PAL_M 4
43#define FB_A320TV_LAST 4
44
45static const char *jzfb_tv_out_norm[] = {
46    "off", "ntsc", "pal", "pal-60", "pal-m",
47};
48
49static struct fb_fix_screeninfo jzfb_fix = {
50    .id = "JZ4740 SLCD FB",
51    .type = FB_TYPE_PACKED_PIXELS,
52    .visual = FB_VISUAL_TRUECOLOR,
53    .xpanstep = 0,
54    .ypanstep = 1,
55    .ywrapstep = 0,
56    .accel = FB_ACCEL_NONE,
57};
58
59const static struct jz_gpio_bulk_request jz_slcd_ctrl_pins[] = {
60    JZ_GPIO_BULK_PIN(LCD_PCLK),
61    JZ_GPIO_BULK_PIN(SLCD_RS),
62    JZ_GPIO_BULK_PIN(SLCD_CS),
63};
64
65const static struct jz_gpio_bulk_request jz_slcd_data_pins[] = {
66    JZ_GPIO_BULK_PIN(LCD_DATA0),
67    JZ_GPIO_BULK_PIN(LCD_DATA1),
68    JZ_GPIO_BULK_PIN(LCD_DATA2),
69    JZ_GPIO_BULK_PIN(LCD_DATA3),
70    JZ_GPIO_BULK_PIN(LCD_DATA4),
71    JZ_GPIO_BULK_PIN(LCD_DATA5),
72    JZ_GPIO_BULK_PIN(LCD_DATA6),
73    JZ_GPIO_BULK_PIN(LCD_DATA7),
74    JZ_GPIO_BULK_PIN(LCD_DATA8),
75    JZ_GPIO_BULK_PIN(LCD_DATA9),
76    JZ_GPIO_BULK_PIN(LCD_DATA10),
77    JZ_GPIO_BULK_PIN(LCD_DATA11),
78    JZ_GPIO_BULK_PIN(LCD_DATA12),
79    JZ_GPIO_BULK_PIN(LCD_DATA13),
80    JZ_GPIO_BULK_PIN(LCD_DATA14),
81    JZ_GPIO_BULK_PIN(LCD_DATA15),
82    JZ_GPIO_BULK_PIN(LCD_DATA16),
83    JZ_GPIO_BULK_PIN(LCD_DATA17),
84};
85
86static unsigned int jzfb_num_ctrl_pins(struct jzfb *jzfb)
87{
88    return ARRAY_SIZE(jz_slcd_ctrl_pins);
89}
90
91static unsigned int jzfb_num_data_pins(struct jzfb *jzfb)
92{
93    switch (jzfb->pdata->lcd_type) {
94    case JZ_LCD_TYPE_SMART_PARALLEL_8_BIT:
95        return 8;
96    case JZ_LCD_TYPE_SMART_PARALLEL_16_BIT:
97        return 16;
98    case JZ_LCD_TYPE_SMART_PARALLEL_18_BIT:
99        return 18;
100    default:
101        return 0;
102    }
103}
104
105static void jzfb_free_gpio_pins(struct jzfb *jzfb)
106{
107    jz_gpio_bulk_free(jz_slcd_ctrl_pins, jzfb_num_ctrl_pins(jzfb));
108    if (jzfb->pdata->lcd_type & (1 << 6)) {
109        /* serial */
110        jz_gpio_bulk_free(&jz_slcd_data_pins[15], 1);
111    } else {
112        /* parallel */
113        jz_gpio_bulk_free(jz_slcd_data_pins,
114                  jzfb_num_data_pins(jzfb));
115    }
116}
117
118static int jzfb_setcolreg(unsigned regno, unsigned red, unsigned green,
119            unsigned blue, unsigned transp, struct fb_info *fb)
120{
121    if (regno >= 16)
122        return -EINVAL;
123
124    red = (red * ((1 << fb->var.red.length ) - 1)) / ((1 << 16) - 1);
125    green = (green * ((1 << fb->var.green.length) - 1)) / ((1 << 16) - 1);
126    blue = (blue * ((1 << fb->var.blue.length ) - 1)) / ((1 << 16) - 1);
127
128    ((uint32_t *)fb->pseudo_palette)[regno] =
129        (red << fb->var.red.offset ) |
130        (green << fb->var.green.offset) |
131        (blue << fb->var.blue.offset );
132
133    return 0;
134}
135
136static int jzfb_get_controller_bpp(struct jzfb *jzfb)
137{
138    switch (jzfb->pdata->bpp) {
139    case 18:
140    case 24:
141        return 32;
142    case 15:
143        return 16;
144    default:
145        return jzfb->pdata->bpp;
146    }
147}
148
149static struct fb_videomode *jzfb_get_mode(struct jzfb *jzfb, struct fb_var_screeninfo *var)
150{
151    size_t i;
152    struct fb_videomode *mode = jzfb->pdata->modes;
153
154    for (i = 0; i < jzfb->pdata->num_modes; ++i, ++mode) {
155        if (mode->xres == var->xres && mode->yres == var->yres)
156            return mode;
157    }
158
159    return NULL;
160}
161
162static int jzfb_check_var(struct fb_var_screeninfo *var, struct fb_info *fb)
163{
164    struct jzfb *jzfb = fb->par;
165    struct fb_videomode *mode;
166
167    if (var->bits_per_pixel != jzfb_get_controller_bpp(jzfb) &&
168        var->bits_per_pixel != jzfb->pdata->bpp)
169        return -EINVAL;
170
171    mode = jzfb_get_mode(jzfb, var);
172    if (mode == NULL)
173        return -EINVAL;
174
175    fb_videomode_to_var(var, mode);
176
177    /* Reserve space for double buffering. */
178    var->yres_virtual = var->yres * 2;
179
180    switch (jzfb->pdata->bpp) {
181    case 8:
182        break;
183    case 15:
184        var->red.offset = 10;
185        var->red.length = 5;
186        var->green.offset = 5;
187        var->green.length = 5;
188        var->blue.offset = 0;
189        var->blue.length = 5;
190        break;
191    case 16:
192        var->red.offset = 11;
193        var->red.length = 5;
194        var->green.offset = 5;
195        var->green.length = 6;
196        var->blue.offset = 0;
197        var->blue.length = 5;
198        break;
199    case 18:
200        var->red.offset = 16;
201        var->red.length = 6;
202        var->green.offset = 8;
203        var->green.length = 6;
204        var->blue.offset = 0;
205        var->blue.length = 6;
206        var->bits_per_pixel = 32;
207        break;
208    case 32:
209    case 24:
210        var->transp.offset = 24;
211        var->transp.length = 8;
212        var->red.offset = 16;
213        var->red.length = 8;
214        var->green.offset = 8;
215        var->green.length = 8;
216        var->blue.offset = 0;
217        var->blue.length = 8;
218        var->bits_per_pixel = 32;
219        break;
220    default:
221        break;
222    }
223
224    return 0;
225}
226
227static void jzfb_disable_dma(struct jzfb *jzfb)
228{
229    jz4740_dma_disable(jzfb->dma);
230    while (readb(jzfb->base + JZ_REG_SLCD_STATE) & SLCD_STATE_BUSY);
231    writeb(readb(jzfb->base + JZ_REG_SLCD_CTRL) & ~SLCD_CTRL_DMA_EN,
232        jzfb->base + JZ_REG_SLCD_CTRL);
233}
234
235static struct jz4740_dma_config jzfb_slcd_dma_config = {
236    .src_width = JZ4740_DMA_WIDTH_32BIT,
237    .dst_width = JZ4740_DMA_WIDTH_16BIT,
238    .transfer_size = JZ4740_DMA_TRANSFER_SIZE_16BYTE,
239    .request_type = JZ4740_DMA_TYPE_SLCD,
240    .flags = JZ4740_DMA_SRC_AUTOINC,
241    .mode = JZ4740_DMA_MODE_BLOCK,
242};
243
244static void jzfb_upload_frame_dma(struct jzfb *jzfb)
245{
246    struct fb_info *fb = jzfb->fb;
247    struct fb_videomode *mode = fb->mode;
248    __u32 offset = fb->fix.line_length * fb->var.yoffset;
249    __u32 size = fb->fix.line_length * mode->yres;
250
251    /* Ensure that the data to be uploaded is in memory. */
252    dma_cache_sync(fb->device, jzfb->vidmem + offset, size,
253               DMA_TO_DEVICE);
254
255    jz4740_dma_set_src_addr(jzfb->dma, jzfb->vidmem_phys + offset);
256    jz4740_dma_set_dst_addr(jzfb->dma,
257                CPHYSADDR(jzfb->base + JZ_REG_SLCD_FIFO));
258    jz4740_dma_set_transfer_count(jzfb->dma, size);
259
260    while (readb(jzfb->base + JZ_REG_SLCD_STATE) & SLCD_STATE_BUSY);
261    writeb(readb(jzfb->base + JZ_REG_SLCD_CTRL) | SLCD_CTRL_DMA_EN,
262        jzfb->base + JZ_REG_SLCD_CTRL);
263    jz4740_dma_enable(jzfb->dma);
264}
265
266static void jzfb_upload_frame_cpu(struct jzfb *jzfb)
267{
268    const int num_pixels = jzfb->fb->mode->xres * jzfb->fb->mode->yres;
269    uint16_t *p = jzfb->vidmem;
270    int i;
271
272    jzfb_disable_dma(jzfb);
273    for (i = 0; i < num_pixels; i++) {
274        uint16_t rgb = *p++;
275        while (readb(jzfb->base + JZ_REG_SLCD_STATE) & SLCD_STATE_BUSY);
276        writel(SLCD_DATA_RS_DATA | rgb, jzfb->base + JZ_REG_SLCD_DATA);
277    }
278}
279
280static void jzfb_refresh_work(struct work_struct *work)
281{
282    struct jzfb *jzfb = container_of(work, struct jzfb, refresh_work.work);
283
284    mutex_lock(&jzfb->lock);
285    if (jzfb->is_enabled) {
286        if (1) {
287            int interval;
288
289            if (jzfb->dma_completion.done) {
290                if (jzfb->refresh_on_pan)
291                    interval = HZ / 5;
292                else
293                    interval = HZ / 60;
294                jzfb->refresh_on_pan = 0;
295
296                INIT_COMPLETION(jzfb->dma_completion);
297                jzfb_upload_frame_dma(jzfb);
298            } else
299                interval = HZ / 250;
300
301            schedule_delayed_work(&jzfb->refresh_work, interval);
302        } else {
303            jzfb_upload_frame_cpu(jzfb);
304            schedule_delayed_work(&jzfb->refresh_work, HZ / 10);
305        }
306    }
307    mutex_unlock(&jzfb->lock);
308}
309
310static int jzfb_set_par(struct fb_info *info)
311{
312    struct jzfb *jzfb = info->par;
313    struct fb_var_screeninfo *var = &info->var;
314    struct fb_videomode *mode;
315    uint16_t slcd_cfg;
316
317    mode = jzfb_get_mode(jzfb, var);
318    if (mode == NULL)
319        return -EINVAL;
320
321    info->mode = mode;
322
323    slcd_cfg = SLCD_CFG_BURST_8_WORD;
324    /* command size */
325    slcd_cfg |= (jzfb->pdata->lcd_type & 3) << SLCD_CFG_CWIDTH_BIT;
326    /* data size */
327    if (jzfb->pdata->lcd_type & (1 << 6)) {
328        /* serial */
329        unsigned int num_bits;
330        switch (jzfb->pdata->lcd_type) {
331        case JZ_LCD_TYPE_SMART_SERIAL_8_BIT:
332            slcd_cfg |= SLCD_CFG_DWIDTH_8_x1;
333            num_bits = 8;
334            break;
335        case JZ_LCD_TYPE_SMART_SERIAL_16_BIT:
336            slcd_cfg |= SLCD_CFG_DWIDTH_16;
337            num_bits = 16;
338            break;
339        case JZ_LCD_TYPE_SMART_SERIAL_18_BIT:
340            slcd_cfg |= SLCD_CFG_DWIDTH_18;
341            num_bits = 18;
342            break;
343        default:
344            num_bits = 0;
345            break;
346        }
347        if (num_bits != jzfb->pdata->bpp) {
348            dev_err(&jzfb->pdev->dev,
349                "Data size (%d) does not match bpp (%d)\n",
350                num_bits, jzfb->pdata->bpp);
351        }
352        slcd_cfg |= SLCD_CFG_TYPE_SERIAL;
353    } else {
354        /* parallel */
355        switch (jzfb->pdata->bpp) {
356        case 8:
357            slcd_cfg |= SLCD_CFG_DWIDTH_8_x1;
358            break;
359        case 15:
360        case 16:
361            switch (jzfb->pdata->lcd_type) {
362            case JZ_LCD_TYPE_SMART_PARALLEL_8_BIT:
363                slcd_cfg |= SLCD_CFG_DWIDTH_8_x2;
364                break;
365            default:
366                slcd_cfg |= SLCD_CFG_DWIDTH_16;
367                break;
368            }
369            break;
370        case 18:
371            switch (jzfb->pdata->lcd_type) {
372            case JZ_LCD_TYPE_SMART_PARALLEL_8_BIT:
373                slcd_cfg |= SLCD_CFG_DWIDTH_8_x3;
374                break;
375            case JZ_LCD_TYPE_SMART_PARALLEL_16_BIT:
376                slcd_cfg |= SLCD_CFG_DWIDTH_9_x2;
377                break;
378            case JZ_LCD_TYPE_SMART_PARALLEL_18_BIT:
379                slcd_cfg |= SLCD_CFG_DWIDTH_18;
380                break;
381            default:
382                break;
383            }
384            break;
385        case 24:
386            slcd_cfg |= SLCD_CFG_DWIDTH_8_x3;
387            break;
388        default:
389            dev_err(&jzfb->pdev->dev,
390                "Unsupported value for bpp: %d\n",
391                jzfb->pdata->bpp);
392        }
393        slcd_cfg |= SLCD_CFG_TYPE_PARALLEL;
394    }
395    if (!jzfb->pdata->chip_select_active_low)
396        slcd_cfg |= SLCD_CFG_CS_ACTIVE_HIGH;
397    if (!jzfb->pdata->register_select_active_low)
398        slcd_cfg |= SLCD_CFG_RS_CMD_HIGH;
399    if (!jzfb->pdata->pixclk_falling_edge)
400        slcd_cfg |= SLCD_CFG_CLK_ACTIVE_RISING;
401
402#if 0
403    // TODO(MtH): Compute rate from refresh or vice versa.
404    if (mode->pixclock) {
405        rate = PICOS2KHZ(mode->pixclock) * 1000;
406        mode->refresh = rate / vt / ht;
407    } else {
408        if (jzfb->pdata->lcd_type == JZ_LCD_TYPE_8BIT_SERIAL)
409            rate = mode->refresh * (vt + 2 * mode->xres) * ht;
410        else
411            rate = mode->refresh * vt * ht;
412
413        mode->pixclock = KHZ2PICOS(rate / 1000);
414    }
415#endif
416
417    mutex_lock(&jzfb->lock);
418    if (!jzfb->is_enabled)
419        clk_enable(jzfb->ldclk);
420
421    // TODO(MtH): We should not change config while DMA might be running.
422    writew(slcd_cfg, jzfb->base + JZ_REG_SLCD_CFG);
423
424    if (!jzfb->is_enabled)
425        clk_disable(jzfb->ldclk);
426    mutex_unlock(&jzfb->lock);
427
428    // TODO(MtH): Use maximum transfer speed that panel can handle.
429    // ILI9325 can do 10 MHz.
430    clk_set_rate(jzfb->lpclk, 12000000);
431    clk_set_rate(jzfb->ldclk, 42000000);
432
433    return 0;
434}
435
436static void jzfb_enable(struct jzfb *jzfb)
437{
438    uint32_t ctrl;
439
440    clk_enable(jzfb->ldclk);
441
442    jz_gpio_bulk_resume(jz_slcd_ctrl_pins, jzfb_num_ctrl_pins(jzfb));
443    if (jzfb->pdata->lcd_type & (1 << 6)) {
444        /* serial */
445        jz_gpio_bulk_resume(&jz_slcd_data_pins[15], 1);
446    } else {
447        /* parallel */
448        jz_gpio_bulk_resume(jz_slcd_data_pins,
449                    jzfb_num_data_pins(jzfb));
450    }
451    jzfb_disable_dma(jzfb);
452    complete_all(&jzfb->dma_completion);
453    jzfb->panel->enable(jzfb);
454
455    ctrl = readl(jzfb->base + JZ_REG_LCD_CTRL);
456    ctrl |= JZ_LCD_CTRL_ENABLE;
457    ctrl &= ~JZ_LCD_CTRL_DISABLE;
458    writel(ctrl, jzfb->base + JZ_REG_LCD_CTRL);
459
460    schedule_delayed_work(&jzfb->refresh_work, 0);
461}
462
463static void jzfb_disable(struct jzfb *jzfb)
464{
465    /* It is safe but wasteful to call refresh_work() while disabled. */
466    cancel_delayed_work_sync(&jzfb->refresh_work);
467
468    /* Abort any DMA transfer that might be in progress and allow direct
469       writes to the panel. */
470    jzfb_disable_dma(jzfb);
471    complete_all(&jzfb->dma_completion);
472
473    jzfb->panel->disable(jzfb);
474    jz_gpio_bulk_suspend(jz_slcd_ctrl_pins, jzfb_num_ctrl_pins(jzfb));
475    if (jzfb->pdata->lcd_type & (1 << 6)) {
476        /* serial */
477        jz_gpio_bulk_suspend(&jz_slcd_data_pins[15], 1);
478    } else {
479        /* parallel */
480        jz_gpio_bulk_suspend(jz_slcd_data_pins,
481                     jzfb_num_data_pins(jzfb));
482    }
483
484    clk_disable(jzfb->ldclk);
485}
486
487static int jzfb_blank(int blank_mode, struct fb_info *info)
488{
489    struct jzfb *jzfb = info->par;
490    int ret = 0;
491    int new_enabled = (blank_mode == FB_BLANK_UNBLANK);
492
493    mutex_lock(&jzfb->lock);
494    if (new_enabled) {
495        if (!jzfb->is_enabled)
496            jzfb_enable(jzfb);
497    } else {
498        if (jzfb->is_enabled) {
499            /* No sleep in TV-out mode. */
500            if (jzfb->tv_out == FB_A320TV_OFF)
501                jzfb_disable(jzfb);
502            else
503                ret = -EBUSY;
504        }
505    }
506    if (!ret)
507        jzfb->is_enabled = new_enabled;
508    mutex_unlock(&jzfb->lock);
509
510    return ret;
511}
512
513static int jzfb_wait_for_vsync(struct fb_info *info)
514{
515    struct jzfb *jzfb = info->par;
516
517    if (jzfb->tv_out != FB_A320TV_OFF &&
518                !jzfb->tv_out_vsync)
519        return 0;
520    return wait_for_completion_interruptible(&jzfb->dma_completion);
521}
522
523static int jzfb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
524{
525    struct jzfb *jzfb = info->par;
526    info->var.yoffset = var->yoffset;
527
528    /* Ensure that the data to be uploaded is in memory. */
529    dma_cache_sync(&jzfb->pdev->dev, jzfb->vidmem
530                + info->fix.line_length * var->yoffset,
531                info->fix.line_length * var->yres,
532                DMA_TO_DEVICE);
533
534    /* update frame start address for TV-out mode */
535    (*jzfb->framedesc)[1].addr = jzfb->vidmem_phys
536                          + info->fix.line_length * var->yoffset;
537
538    jzfb_wait_for_vsync(info);
539
540    jzfb->refresh_on_pan = 1;
541    flush_delayed_work(&jzfb->refresh_work);
542    return 0;
543}
544
545static int jzfb_mmap(struct fb_info *info, struct vm_area_struct *vma)
546{
547    const unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;
548    const unsigned long size = vma->vm_end - vma->vm_start;
549
550    if (offset + size > info->fix.smem_len)
551        return -EINVAL;
552
553    if (remap_pfn_range(vma, vma->vm_start,
554                (info->fix.smem_start + offset) >> PAGE_SHIFT,
555                size, vma->vm_page_prot))
556        return -EAGAIN;
557
558    return 0;
559}
560
561static int jzfb_alloc_devmem(struct jzfb *jzfb)
562{
563    int max_linesize = 0, max_framesize = 0;
564    int bytes_per_pixel;
565    struct fb_videomode *mode = jzfb->pdata->modes;
566    void *page;
567    int i;
568
569    for (i = 0; i < jzfb->pdata->num_modes; ++mode, ++i) {
570        if (max_linesize < mode->xres)
571            max_linesize = mode->xres;
572        if (max_framesize < mode->xres * mode->yres)
573            max_framesize = mode->xres * mode->yres;
574    }
575
576    bytes_per_pixel = jzfb_get_controller_bpp(jzfb) >> 3;
577    max_linesize *= bytes_per_pixel;
578    max_framesize *= bytes_per_pixel;
579
580    jzfb->framedesc = dma_alloc_coherent(&jzfb->pdev->dev,
581                    sizeof(*jzfb->framedesc),
582                    &jzfb->framedesc_phys, GFP_KERNEL);
583    if (!jzfb->framedesc)
584        return -ENOMEM;
585
586    jzfb->blackline_size = max_linesize;
587    jzfb->blackline = dma_alloc_coherent(&jzfb->pdev->dev,
588                         jzfb->blackline_size,
589                         &jzfb->blackline_phys, GFP_KERNEL);
590    if (!jzfb->blackline)
591        goto err_free_framedesc;
592
593    /* Set the black line to black... */
594    memset(jzfb->blackline, 0, jzfb->blackline_size);
595
596    /* reserve memory for two frames to allow double buffering */
597    jzfb->vidmem_size = PAGE_ALIGN(max_framesize * 2);
598    jzfb->vidmem = dma_alloc_coherent(&jzfb->pdev->dev,
599                        jzfb->vidmem_size,
600                        &jzfb->vidmem_phys, GFP_KERNEL);
601
602    if (!jzfb->vidmem)
603        goto err_free_blackline;
604
605    for (page = jzfb->vidmem;
606         page < jzfb->vidmem + PAGE_ALIGN(jzfb->vidmem_size);
607         page += PAGE_SIZE) {
608        SetPageReserved(virt_to_page(page));
609    }
610
611    for (i = 0; i < 3; i++)
612        (*jzfb->framedesc)[i].next = jzfb->framedesc_phys
613                + ((i + 1) % 3) * sizeof(struct jzfb_framedesc);
614    (*jzfb->framedesc)[0].addr = (*jzfb->framedesc)[2].addr =
615            jzfb->blackline_phys;
616    (*jzfb->framedesc)[0].id = 0xdadabeeb;
617    (*jzfb->framedesc)[2].id = 0xfadefeed;
618    (*jzfb->framedesc)[0].cmd = (*jzfb->framedesc)[2].cmd =
619            jzfb->blackline_size / 4;
620    (*jzfb->framedesc)[1].addr = jzfb->vidmem_phys;
621    (*jzfb->framedesc)[1].id = 0xdeafbead;
622    (*jzfb->framedesc)[1].cmd = (max_framesize / 4)
623            | JZ_LCD_CMD_EOF_IRQ | JZ_LCD_CMD_SOF_IRQ;
624
625    return 0;
626
627err_free_blackline:
628    dma_free_coherent(&jzfb->pdev->dev, jzfb->blackline_size,
629                jzfb->blackline, jzfb->blackline_phys);
630err_free_framedesc:
631    dma_free_coherent(&jzfb->pdev->dev, sizeof(*jzfb->framedesc),
632                jzfb->framedesc, jzfb->framedesc_phys);
633    return -ENOMEM;
634}
635
636static void jzfb_free_devmem(struct jzfb *jzfb)
637{
638    dma_free_coherent(&jzfb->pdev->dev, jzfb->vidmem_size,
639                jzfb->vidmem, jzfb->vidmem_phys);
640    dma_free_coherent(&jzfb->pdev->dev, jzfb->blackline_size,
641                jzfb->blackline, jzfb->blackline_phys);
642    dma_free_coherent(&jzfb->pdev->dev, sizeof(*jzfb->framedesc),
643                jzfb->framedesc, jzfb->framedesc_phys);
644}
645
646static int jzfb_tv_out(struct jzfb *jzfb, unsigned int mode)
647{
648    int blank = jzfb->is_enabled ? FB_BLANK_UNBLANK : FB_BLANK_POWERDOWN;
649    struct fb_event event = {
650        .info = jzfb->fb,
651        .data = &blank,
652    };
653
654    printk("A320 TV out: %d\n", mode);
655    if (mode > FB_A320TV_LAST)
656        return -EINVAL;
657    if (mode == jzfb->tv_out)
658        return 0;
659
660    if (mode != FB_A320TV_OFF) {
661        cancel_delayed_work_sync(&jzfb->refresh_work);
662        /* Abort any DMA transfer that might be in progress and
663           allow direct writes to the panel. */
664        jzfb_disable_dma(jzfb);
665        jzfb->panel->disable(jzfb);
666        complete_all(&jzfb->dma_completion);
667
668        /* set up LCD controller for TV output */
669
670        writel(JZ_LCD_CFG_HSYNC_ACTIVE_LOW |
671               JZ_LCD_CFG_VSYNC_ACTIVE_LOW,
672               jzfb->base + JZ_REG_LCD_CFG);
673
674        /* V-Sync pulse end position */
675        writel(10, jzfb->base + JZ_REG_LCD_VSYNC);
676
677        if (mode == FB_A320TV_PAL50) {
678            /* PAL 50 Hz */
679            /* H-Sync pulse start position */
680            writel(0x0000007d, jzfb->base + JZ_REG_LCD_HSYNC);
681            /* virtual area size */
682            writel(0x036c0112, jzfb->base + JZ_REG_LCD_VAT);
683            /* horizontal start/end point */
684            writel(0x02240364, jzfb->base + JZ_REG_LCD_DAH);
685            /* vertical start/end point */
686            writel(0x001a010c, jzfb->base + JZ_REG_LCD_DAV);
687        } else {
688            /* NTSC and PAL 60 Hz */
689            writel(0x0000003c, jzfb->base + JZ_REG_LCD_HSYNC);
690            writel(0x02e00110, jzfb->base + JZ_REG_LCD_VAT);
691            writel(0x019902d9, jzfb->base + JZ_REG_LCD_DAH);
692            writel(0x001c010e, jzfb->base + JZ_REG_LCD_DAV);
693        }
694        writel(0, jzfb->base + JZ_REG_LCD_PS);
695        writel(0, jzfb->base + JZ_REG_LCD_CLS);
696        writel(0, jzfb->base + JZ_REG_LCD_SPL);
697        writel(0, jzfb->base + JZ_REG_LCD_REV);
698        /* reset status register */
699        writel(0, jzfb->base + JZ_REG_LCD_STATE);
700
701        /* tell LCDC about the frame descriptor address */
702        writel(jzfb->framedesc_phys, jzfb->base + JZ_REG_LCD_DA0);
703
704        writel(JZ_LCD_CTRL_BURST_16 | JZ_LCD_CTRL_ENABLE |
705                    JZ_LCD_CTRL_BPP_15_16 |
706                    JZ_LCD_CTRL_EOF_IRQ | JZ_LCD_CTRL_SOF_IRQ,
707                    jzfb->base + JZ_REG_LCD_CTRL);
708    } else {
709        /* disable EOF/SOF interrupts */
710        unsigned long ctrl = readl(jzfb->base + JZ_REG_LCD_CTRL);
711        ctrl &= ~(JZ_LCD_CTRL_EOF_IRQ | JZ_LCD_CTRL_SOF_IRQ);
712        writel(ctrl, jzfb->base + JZ_REG_LCD_CTRL);
713
714        /* disable LCD controller and re-enable SLCD */
715        writel(JZ_LCD_CFG_SLCD, jzfb->base + JZ_REG_LCD_CFG);
716        jzfb->panel->enable(jzfb);
717
718        jzfb->refresh_on_pan = 0;
719        complete_all(&jzfb->dma_completion);
720        schedule_delayed_work(&jzfb->refresh_work, 0);
721    }
722
723    /* reaffirm the current blanking state, to trigger a backlight update */
724    console_lock();
725    fb_notifier_call_chain(FB_EVENT_BLANK, &event);
726    console_unlock();
727    jzfb->tv_out = mode;
728    return 0;
729}
730
731static ssize_t jzfb_tv_out_show(struct device *dev, struct device_attribute *attr,
732            char *buf)
733{
734    struct jzfb *jzfb = dev_get_drvdata(dev);
735
736    if (jzfb->tv_out > FB_A320TV_LAST) {
737        dev_err(dev, "Unknown norm for TV-out\n");
738        return -1;
739    }
740
741    return sprintf(buf, "%s\n", jzfb_tv_out_norm[jzfb->tv_out]);
742}
743
744static ssize_t jzfb_tv_out_store(struct device *dev, struct device_attribute *attr,
745            const char *buf, size_t n)
746{
747    size_t i;
748    struct jzfb *jzfb = dev_get_drvdata(dev);
749
750    for (i = 0; i <= FB_A320TV_LAST; i++) {
751        if (sysfs_streq(jzfb_tv_out_norm[i], buf)) {
752            jzfb_tv_out(jzfb, i);
753            return n;
754        }
755    }
756    return -EINVAL;
757}
758
759static DEVICE_ATTR(tv_out, 0644, jzfb_tv_out_show, jzfb_tv_out_store);
760
761static ssize_t jzfb_vsync_show(struct device *dev, struct device_attribute *attr,
762            char *buf)
763{
764    struct jzfb *jzfb = dev_get_drvdata(dev);
765    return sprintf(buf, "%u\n", jzfb->tv_out_vsync);
766}
767
768static ssize_t jzfb_vsync_store(struct device *dev, struct device_attribute *attr,
769            const char *buf, size_t n)
770{
771    struct jzfb *jzfb = dev_get_drvdata(dev);
772    unsigned int vsync;
773
774    if (sscanf(buf, "%u", &vsync) < 1)
775        return -EINVAL;
776
777    jzfb->tv_out_vsync = vsync;
778    return n;
779}
780
781static DEVICE_ATTR(tv_out_vsync, 0644, jzfb_vsync_show, jzfb_vsync_store);
782
783static ssize_t jzfb_panel_show(struct device *dev, struct device_attribute *attr,
784            char *buf)
785{
786    struct jzfb *jzfb = dev_get_drvdata(dev);
787    return sprintf(buf, "%s\n", jzfb->panel->name);
788}
789
790static ssize_t jzfb_panel_store(struct device *dev, struct device_attribute *attr,
791            const char *buf, size_t n)
792{
793    struct jzfb *jzfb = dev_get_drvdata(dev);
794    const struct jz_slcd_panel *panel = jz_slcd_panel_from_name(buf);
795
796    if (!panel) {
797        dev_err(dev, "Unknown SLCD panel: %s\n", buf);
798        return -EINVAL;
799    }
800
801    if (panel != jzfb->panel) {
802        jzfb->panel->disable(jzfb);
803        jzfb->panel->exit(jzfb);
804        jzfb->panel = panel;
805        panel->init(jzfb);
806        panel->enable(jzfb);
807    }
808    return n;
809}
810
811static DEVICE_ATTR(panel, 0644, jzfb_panel_show, jzfb_panel_store);
812
813static struct fb_ops jzfb_ops = {
814    .owner = THIS_MODULE,
815    .fb_check_var = jzfb_check_var,
816    .fb_set_par = jzfb_set_par,
817    .fb_setcolreg = jzfb_setcolreg,
818    .fb_blank = jzfb_blank,
819    .fb_pan_display = jzfb_pan_display,
820    .fb_fillrect = sys_fillrect,
821    .fb_copyarea = sys_copyarea,
822    .fb_imageblit = sys_imageblit,
823    .fb_mmap = jzfb_mmap,
824};
825
826static irqreturn_t jz4740_lcd_irq(int irq, void *dev_id)
827{
828    struct jzfb *jzfb = dev_id;
829    unsigned long state = readl(jzfb->base + JZ_REG_LCD_STATE);
830
831    if (state & JZ_LCD_STATE_SOF) {
832        INIT_COMPLETION(jzfb->dma_completion);
833        state &= ~JZ_LCD_STATE_SOF;
834    } else {
835        complete_all(&jzfb->dma_completion);
836        state &= ~JZ_LCD_STATE_EOF;
837    }
838
839    /* Acknowledge the interrupt */
840    writel(state, jzfb->base + JZ_REG_LCD_STATE);
841    return IRQ_HANDLED;
842}
843
844static int jzfb_probe(struct platform_device *pdev)
845{
846    int ret;
847    struct jzfb *jzfb;
848    struct fb_info *fb;
849    struct jz4740_fb_platform_data *pdata = pdev->dev.platform_data;
850    struct resource *mem;
851
852    if (!pdata) {
853        dev_err(&pdev->dev, "Missing platform data\n");
854        return -ENOENT;
855    }
856
857    fb = framebuffer_alloc(sizeof(struct jzfb), &pdev->dev);
858
859    if (!fb) {
860        dev_err(&pdev->dev, "Failed to allocate framebuffer device\n");
861        return -ENOMEM;
862    }
863
864    fb->fbops = &jzfb_ops;
865    fb->flags = FBINFO_DEFAULT;
866
867    jzfb = fb->par;
868    jzfb->pdata = pdata;
869    jzfb->pdev = pdev;
870
871    mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
872    jzfb->base = devm_ioremap_resource(&pdev->dev, mem);
873    if (IS_ERR(jzfb->base)) {
874        ret = PTR_ERR(jzfb->base);
875        goto err_framebuffer_release;
876    }
877
878    jzfb->tv_out = FB_A320TV_OFF;
879    jzfb->tv_out_vsync = 1;
880    jzfb->refresh_on_pan = 0;
881    init_completion(&jzfb->dma_completion);
882    complete_all(&jzfb->dma_completion);
883
884    jzfb->dma = jz4740_dma_request(&pdev->dev, dev_name(&pdev->dev), 0);
885    if (!jzfb->dma) {
886        dev_err(&pdev->dev, "Failed to get DMA channel\n");
887        ret = -EBUSY;
888        goto err_framebuffer_release;
889    }
890    jz4740_dma_configure(jzfb->dma, &jzfb_slcd_dma_config);
891    jz4740_dma_set_complete_cb(jzfb->dma, &jzfb_refresh_work_complete);
892
893    jzfb->ldclk = clk_get(&pdev->dev, "lcd");
894    if (IS_ERR(jzfb->ldclk)) {
895        ret = PTR_ERR(jzfb->ldclk);
896        dev_err(&pdev->dev, "Failed to get lcd clock: %d\n", ret);
897        goto err_free_dma;
898    }
899
900    jzfb->lpclk = clk_get(&pdev->dev, "lcd_pclk");
901    if (IS_ERR(jzfb->lpclk)) {
902        ret = PTR_ERR(jzfb->lpclk);
903        dev_err(&pdev->dev, "Failed to get lcd pixel clock: %d\n", ret);
904        goto err_put_ldclk;
905    }
906
907    platform_set_drvdata(pdev, jzfb);
908
909    fb_videomode_to_modelist(pdata->modes, pdata->num_modes,
910                 &fb->modelist);
911    fb->mode = pdata->modes;
912
913    fb_videomode_to_var(&fb->var, fb->mode);
914    fb->var.bits_per_pixel = pdata->bpp;
915    jzfb_check_var(&fb->var, fb);
916
917    ret = jzfb_alloc_devmem(jzfb);
918    if (ret) {
919        dev_err(&pdev->dev, "Failed to allocate video memory\n");
920        goto err_put_lpclk;
921    }
922
923    fb->fix = jzfb_fix;
924    fb->fix.line_length = fb->var.bits_per_pixel * fb->var.xres / 8;
925    fb->fix.mmio_start = mem->start;
926    fb->fix.mmio_len = resource_size(mem);
927    fb->fix.smem_start = jzfb->vidmem_phys;
928    fb->fix.smem_len = fb->fix.line_length * fb->var.yres_virtual;
929    fb->screen_base = jzfb->vidmem;
930    fb->pseudo_palette = jzfb->pseudo_palette;
931
932    fb_alloc_cmap(&fb->cmap, 256, 0);
933
934    mutex_init(&jzfb->lock);
935
936    clk_enable(jzfb->ldclk);
937    jzfb->is_enabled = 1;
938
939    writel(JZ_LCD_CFG_SLCD, jzfb->base + JZ_REG_LCD_CFG);
940    writeb(0, jzfb->base + JZ_REG_SLCD_CTRL);
941
942    jzfb_set_par(fb);
943
944    jz_gpio_bulk_request(jz_slcd_ctrl_pins, jzfb_num_ctrl_pins(jzfb));
945    if (jzfb->pdata->lcd_type & (1 << 6)) {
946        /* serial */
947        jz_gpio_bulk_request(&jz_slcd_data_pins[15], 1);
948    } else {
949        /* parallel */
950        jz_gpio_bulk_request(jz_slcd_data_pins,
951                     jzfb_num_data_pins(jzfb));
952    }
953
954    ret = request_irq(JZ4740_IRQ_LCD, jz4740_lcd_irq, 0, "LCD", jzfb);
955    if (ret) {
956        dev_err(&pdev->dev, "Failed to request IRQ\n");
957        goto err_free_devmem;
958    }
959
960    jzfb->panel = jz_slcd_panels_probe(jzfb);
961    if (!jzfb->panel) {
962        dev_err(&pdev->dev, "Failed to find panel driver\n");
963        ret = -ENOENT;
964        goto err_free_irq;
965    }
966    jzfb_disable_dma(jzfb);
967    jzfb->panel->init(jzfb);
968
969    jzfb->panel->enable(jzfb);
970
971    ret = register_framebuffer(fb);
972    if (ret) {
973        dev_err(&pdev->dev, "Failed to register framebuffer: %d\n", ret);
974        goto err_free_panel;
975    }
976
977    jzfb->fb = fb;
978    fb_prepare_logo(jzfb->fb, 0);
979    fb_show_logo(jzfb->fb, 0);
980
981    INIT_DELAYED_WORK(&jzfb->refresh_work, jzfb_refresh_work);
982    schedule_delayed_work(&jzfb->refresh_work, 0);
983
984    ret = device_create_file(&pdev->dev, &dev_attr_panel);
985    if (ret)
986        goto err_cancel_work;
987
988    ret = device_create_file(&pdev->dev, &dev_attr_tv_out);
989    if (ret)
990        goto err_remove_file_panel;
991
992    ret = device_create_file(&pdev->dev, &dev_attr_tv_out_vsync);
993    if (!ret)
994        return 0;
995
996    device_remove_file(&pdev->dev, &dev_attr_tv_out);
997err_remove_file_panel:
998    device_remove_file(&pdev->dev, &dev_attr_panel);
999err_cancel_work:
1000    cancel_delayed_work_sync(&jzfb->refresh_work);
1001err_free_panel:
1002    jzfb->panel->exit(jzfb);
1003err_free_irq:
1004    free_irq(JZ4740_IRQ_LCD, jzfb);
1005err_free_devmem:
1006    jzfb_free_gpio_pins(jzfb);
1007
1008    fb_dealloc_cmap(&fb->cmap);
1009    jzfb_free_devmem(jzfb);
1010err_put_lpclk:
1011    clk_put(jzfb->lpclk);
1012err_put_ldclk:
1013    clk_put(jzfb->ldclk);
1014err_free_dma:
1015    jz4740_dma_free(jzfb->dma);
1016err_framebuffer_release:
1017    framebuffer_release(fb);
1018    return ret;
1019}
1020
1021static int jzfb_remove(struct platform_device *pdev)
1022{
1023    struct jzfb *jzfb = platform_get_drvdata(pdev);
1024
1025    device_remove_file(&pdev->dev, &dev_attr_tv_out_vsync);
1026    device_remove_file(&pdev->dev, &dev_attr_tv_out);
1027    device_remove_file(&pdev->dev, &dev_attr_panel);
1028    jzfb_blank(FB_BLANK_POWERDOWN, jzfb->fb);
1029
1030    free_irq(JZ4740_IRQ_LCD, jzfb);
1031
1032    /* Blanking will prevent future refreshes from behind scheduled.
1033       Now wait for a possible refresh in progress to finish. */
1034    cancel_delayed_work_sync(&jzfb->refresh_work);
1035
1036    jzfb->panel->exit(jzfb);
1037
1038    jzfb_free_gpio_pins(jzfb);
1039
1040    jz4740_dma_free(jzfb->dma);
1041
1042    fb_dealloc_cmap(&jzfb->fb->cmap);
1043    jzfb_free_devmem(jzfb);
1044
1045    platform_set_drvdata(pdev, NULL);
1046
1047    clk_put(jzfb->lpclk);
1048    clk_put(jzfb->ldclk);
1049
1050    framebuffer_release(jzfb->fb);
1051
1052    return 0;
1053}
1054
1055#ifdef CONFIG_PM
1056
1057static int jzfb_suspend(struct device *dev)
1058{
1059    struct jzfb *jzfb = dev_get_drvdata(dev);
1060
1061    console_lock();
1062    fb_set_suspend(jzfb->fb, 1);
1063    console_unlock();
1064
1065    mutex_lock(&jzfb->lock);
1066    if (jzfb->is_enabled)
1067        jzfb_disable(jzfb);
1068    mutex_unlock(&jzfb->lock);
1069
1070    return 0;
1071}
1072
1073static int jzfb_resume(struct device *dev)
1074{
1075    struct jzfb *jzfb = dev_get_drvdata(dev);
1076
1077    mutex_lock(&jzfb->lock);
1078    if (jzfb->is_enabled)
1079        jzfb_enable(jzfb);
1080    mutex_unlock(&jzfb->lock);
1081
1082    console_lock();
1083    fb_set_suspend(jzfb->fb, 0);
1084    console_unlock();
1085
1086    return 0;
1087}
1088
1089static SIMPLE_DEV_PM_OPS(jzfb_pm_ops, jzfb_suspend, jzfb_resume);
1090
1091#define JZFB_PM_OPS (&jzfb_pm_ops)
1092
1093#else
1094#define JZFB_PM_OPS NULL
1095#endif
1096
1097static struct platform_driver jzfb_driver = {
1098    .probe = jzfb_probe,
1099    .remove = jzfb_remove,
1100    .driver = {
1101        .name = "jz4740-fb",
1102        .pm = JZFB_PM_OPS,
1103    },
1104};
1105module_platform_driver(jzfb_driver);
1106
1107MODULE_LICENSE("GPL");
1108MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>, Maarten ter Huurne <maarten@treewalker.org>");
1109MODULE_DESCRIPTION("JZ4740 SoC SLCD framebuffer driver");
1110MODULE_ALIAS("platform:jz4740-fb");
drivers/video/fbdev/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