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