/
0048-video-da8xx-fb-CCF-clock-divider-handling.patch
168 lines (151 loc) · 4.96 KB
/
0048-video-da8xx-fb-CCF-clock-divider-handling.patch
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
From 18d93d53f17f028c0bbcb9fd273d0637796e3160 Mon Sep 17 00:00:00 2001
From: Afzal Mohammed <afzal@ti.com>
Date: Wed, 16 Jan 2013 18:14:31 +0530
Subject: [PATCH 48/48] video: da8xx-fb: CCF clock divider handling
Common clock framework provides a basic clock divider. Make use of it
to handle clock configuration in the LCDC IP, wherever applicable;
out of two platforms having this IP, only am335x is converted to use
CCF, DaVinci is not yet converted. Hence wrap the modification such
that it will come into effect only if CCF is selected, otherwise,
prgram dividers as earlier. Once DaVinci is converted to use CCF,
this ifdef'ery can be removed.
Divider clock instantiated is made as a one that allows the rate
propogation to it's parent, that provides more options w.r.t pixel
clock rates that could be configured.
Signed-off-by: Afzal Mohammed <afzal@ti.com>
---
drivers/video/da8xx-fb.c | 72 ++++++++++++++++++++++++++++++++++++++++++++++--
1 file changed, 70 insertions(+), 2 deletions(-)
diff --git a/drivers/video/da8xx-fb.c b/drivers/video/da8xx-fb.c
index 5455682..6723683 100644
--- a/drivers/video/da8xx-fb.c
+++ b/drivers/video/da8xx-fb.c
@@ -36,6 +36,7 @@
#include <linux/slab.h>
#include <linux/delay.h>
#include <linux/lcm.h>
+#include <linux/clk-provider.h>
#include <video/of_display_timing.h>
#include <video/da8xx-fb.h>
#include <asm/div64.h>
@@ -133,6 +134,10 @@
#define WSI_TIMEOUT 50
#define PALETTE_SIZE 256
+#define LCD_CLK_SHIFT 8
+#define LCD_CLK_WIDTH 8
+#define LCD_CLK_MIN_DIV 2
+
static void __iomem *da8xx_fb_reg_base;
static struct resource *lcdc_regs;
static unsigned int lcd_revision;
@@ -181,6 +186,9 @@ struct da8xx_fb_par {
u32 pseudo_palette[16];
struct fb_videomode mode;
struct lcd_ctrl_config cfg;
+#ifdef CONFIG_COMMON_CLK
+ struct clk *child_clk;
+#endif
};
static struct fb_var_screeninfo da8xx_fb_var;
@@ -683,12 +691,27 @@ static void da8xx_fb_lcd_reset(void)
}
}
+#ifndef CONFIG_COMMON_CLK
static inline unsigned da8xx_fb_calc_clk_divider(struct da8xx_fb_par *par,
unsigned pixclock)
{
return par->lcd_fck_rate / (PICOS2KHZ(pixclock) * 1000);
}
+#endif
+#ifdef CONFIG_COMMON_CLK
+static inline unsigned da8xx_fb_round_clk(struct da8xx_fb_par *par,
+ unsigned pixclock)
+{
+ unsigned long rate;
+
+ rate = PICOS2KHZ(pixclock) * 1000;
+ rate = clk_round_rate(par->child_clk, rate);
+ rate = KHZ2PICOS(rate / 1000);
+
+ return rate;
+}
+#else
static inline unsigned da8xx_fb_round_clk(struct da8xx_fb_par *par,
unsigned pixclock)
{
@@ -703,19 +726,43 @@ static inline void da8xx_fb_config_clk_divider(unsigned div)
/* Configure the LCD clock divisor. */
lcdc_write(LCD_CLK_DIVISOR(div) |
(LCD_RASTER_MODE & 0x1), LCD_CTRL_REG);
+}
+#endif
+static inline void da8xx_fb_clkc_enable(void)
+{
if (lcd_revision == LCD_VERSION_2)
lcdc_write(LCD_V2_DMA_CLK_EN | LCD_V2_LIDD_CLK_EN |
LCD_V2_CORE_CLK_EN, LCD_CLK_ENABLE_REG);
}
-static inline void da8xx_fb_calc_config_clk_divider(struct da8xx_fb_par *par,
+#ifdef CONFIG_COMMON_CLK
+static inline int da8xx_fb_calc_config_clk_divider(struct da8xx_fb_par *par,
+ struct fb_videomode *mode)
+{
+ int ret;
+
+ ret = clk_set_rate(par->child_clk, PICOS2KHZ(mode->pixclock) * 1000);
+ if (IS_ERR_VALUE(ret)) {
+ dev_err(par->dev, "unable to setup pixel clock of %u ps",
+ mode->pixclock);
+ return ret;
+ }
+ da8xx_fb_clkc_enable();
+ return 0;
+}
+#else
+static inline int da8xx_fb_calc_config_clk_divider(struct da8xx_fb_par *par,
struct fb_videomode *mode)
{
unsigned div = da8xx_fb_calc_clk_divider(par, mode->pixclock);
da8xx_fb_config_clk_divider(div);
+ da8xx_fb_clkc_enable();
+
+ return 0;
}
+#endif
static int lcd_init(struct da8xx_fb_par *par, const struct lcd_ctrl_config *cfg,
struct fb_videomode *panel)
@@ -723,7 +770,9 @@ static int lcd_init(struct da8xx_fb_par *par, const struct lcd_ctrl_config *cfg,
u32 bpp;
int ret = 0;
- da8xx_fb_calc_config_clk_divider(par, panel);
+ ret = da8xx_fb_calc_config_clk_divider(par, panel);
+ if (IS_ERR_VALUE(ret))
+ return ret;
if (panel->sync & FB_SYNC_CLK_INVERT)
lcdc_write((lcdc_read(LCD_RASTER_TIMING_2_REG) |
@@ -1406,6 +1455,25 @@ static int fb_probe(struct platform_device *device)
da8xx_fb_lcd_reset();
+#ifdef CONFIG_COMMON_CLK
+ /* set sane divisor value to begin along with the mode */
+ lcdc_write(LCD_RASTER_MODE | LCD_CLK_DIVISOR(LCD_CLK_MIN_DIV),
+ LCD_CTRL_REG);
+
+ par->child_clk = clk_register_min_divider(NULL, "da8xx_fb_clk",
+ __clk_get_name(fb_clk),
+ CLK_SET_RATE_PARENT,
+ da8xx_fb_reg_base + LCD_CTRL_REG,
+ LCD_CLK_SHIFT, LCD_CLK_WIDTH,
+ LCD_CLK_MIN_DIV,
+ CLK_DIVIDER_ONE_BASED, NULL);
+ if (IS_ERR(par->child_clk)) {
+ dev_err(&device->dev, "error registering clk\n");
+ ret = -ENODEV;
+ goto err_release_fb;
+ }
+#endif
+
/* allocate frame buffer */
par->vram_size = lcdc_info->xres * lcdc_info->yres * lcd_cfg->bpp;
ulcm = lcm((lcdc_info->xres * lcd_cfg->bpp)/8, PAGE_SIZE);
--
1.8.2.1