GNU Linux-libre 4.14.266-gnu1
[releases.git] / drivers / gpu / drm / rcar-du / rcar_du_lvdsenc.c
1 /*
2  * rcar_du_lvdsenc.c  --  R-Car Display Unit LVDS Encoder
3  *
4  * Copyright (C) 2013-2014 Renesas Electronics Corporation
5  *
6  * Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com)
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 as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  */
13
14 #include <linux/clk.h>
15 #include <linux/delay.h>
16 #include <linux/io.h>
17 #include <linux/platform_device.h>
18 #include <linux/slab.h>
19
20 #include "rcar_du_drv.h"
21 #include "rcar_du_encoder.h"
22 #include "rcar_du_lvdsenc.h"
23 #include "rcar_lvds_regs.h"
24
25 struct rcar_du_lvdsenc {
26         struct rcar_du_device *dev;
27
28         unsigned int index;
29         void __iomem *mmio;
30         struct clk *clock;
31         bool enabled;
32
33         enum rcar_lvds_input input;
34         enum rcar_lvds_mode mode;
35 };
36
37 static void rcar_lvds_write(struct rcar_du_lvdsenc *lvds, u32 reg, u32 data)
38 {
39         iowrite32(data, lvds->mmio + reg);
40 }
41
42 static void rcar_du_lvdsenc_start_gen2(struct rcar_du_lvdsenc *lvds,
43                                        struct rcar_du_crtc *rcrtc)
44 {
45         const struct drm_display_mode *mode = &rcrtc->crtc.mode;
46         unsigned int freq = mode->clock;
47         u32 lvdcr0;
48         u32 pllcr;
49
50         /* PLL clock configuration */
51         if (freq < 39000)
52                 pllcr = LVDPLLCR_CEEN | LVDPLLCR_COSEL | LVDPLLCR_PLLDLYCNT_38M;
53         else if (freq < 61000)
54                 pllcr = LVDPLLCR_CEEN | LVDPLLCR_COSEL | LVDPLLCR_PLLDLYCNT_60M;
55         else if (freq < 121000)
56                 pllcr = LVDPLLCR_CEEN | LVDPLLCR_COSEL | LVDPLLCR_PLLDLYCNT_121M;
57         else
58                 pllcr = LVDPLLCR_PLLDLYCNT_150M;
59
60         rcar_lvds_write(lvds, LVDPLLCR, pllcr);
61
62         /* Select the input and set the LVDS mode. */
63         lvdcr0 = lvds->mode << LVDCR0_LVMD_SHIFT;
64         if (rcrtc->index == 2)
65                 lvdcr0 |= LVDCR0_DUSEL;
66         rcar_lvds_write(lvds, LVDCR0, lvdcr0);
67
68         /* Turn all the channels on. */
69         rcar_lvds_write(lvds, LVDCR1,
70                         LVDCR1_CHSTBY_GEN2(3) | LVDCR1_CHSTBY_GEN2(2) |
71                         LVDCR1_CHSTBY_GEN2(1) | LVDCR1_CHSTBY_GEN2(0) |
72                         LVDCR1_CLKSTBY_GEN2);
73
74         /* Enable LVDS operation and turn bias circuitry on. */
75         lvdcr0 |= LVDCR0_BEN | LVDCR0_LVEN;
76         rcar_lvds_write(lvds, LVDCR0, lvdcr0);
77
78         /*
79          * Turn the PLL on, wait for the startup delay, and turn the output
80          * on.
81          */
82         lvdcr0 |= LVDCR0_PLLON;
83         rcar_lvds_write(lvds, LVDCR0, lvdcr0);
84
85         usleep_range(100, 150);
86
87         lvdcr0 |= LVDCR0_LVRES;
88         rcar_lvds_write(lvds, LVDCR0, lvdcr0);
89 }
90
91 static void rcar_du_lvdsenc_start_gen3(struct rcar_du_lvdsenc *lvds,
92                                        struct rcar_du_crtc *rcrtc)
93 {
94         const struct drm_display_mode *mode = &rcrtc->crtc.mode;
95         unsigned int freq = mode->clock;
96         u32 lvdcr0;
97         u32 pllcr;
98
99         /* Set the PLL clock configuration and LVDS mode. */
100         if (freq < 42000)
101                 pllcr = LVDPLLCR_PLLDIVCNT_42M;
102         else if (freq < 85000)
103                 pllcr = LVDPLLCR_PLLDIVCNT_85M;
104         else if (freq < 128000)
105                 pllcr = LVDPLLCR_PLLDIVCNT_128M;
106         else
107                 pllcr = LVDPLLCR_PLLDIVCNT_148M;
108
109         rcar_lvds_write(lvds, LVDPLLCR, pllcr);
110
111         lvdcr0 = lvds->mode << LVDCR0_LVMD_SHIFT;
112         rcar_lvds_write(lvds, LVDCR0, lvdcr0);
113
114         /* Turn all the channels on. */
115         rcar_lvds_write(lvds, LVDCR1,
116                         LVDCR1_CHSTBY_GEN3(3) | LVDCR1_CHSTBY_GEN3(2) |
117                         LVDCR1_CHSTBY_GEN3(1) | LVDCR1_CHSTBY_GEN3(0) |
118                         LVDCR1_CLKSTBY_GEN3);
119
120         /*
121          * Turn the PLL on, set it to LVDS normal mode, wait for the startup
122          * delay and turn the output on.
123          */
124         lvdcr0 |= LVDCR0_PLLON;
125         rcar_lvds_write(lvds, LVDCR0, lvdcr0);
126
127         lvdcr0 |= LVDCR0_PWD;
128         rcar_lvds_write(lvds, LVDCR0, lvdcr0);
129
130         usleep_range(100, 150);
131
132         lvdcr0 |= LVDCR0_LVRES;
133         rcar_lvds_write(lvds, LVDCR0, lvdcr0);
134 }
135
136 static int rcar_du_lvdsenc_start(struct rcar_du_lvdsenc *lvds,
137                                  struct rcar_du_crtc *rcrtc)
138 {
139         u32 lvdhcr;
140         int ret;
141
142         if (lvds->enabled)
143                 return 0;
144
145         ret = clk_prepare_enable(lvds->clock);
146         if (ret < 0)
147                 return ret;
148
149         /*
150          * Hardcode the channels and control signals routing for now.
151          *
152          * HSYNC -> CTRL0
153          * VSYNC -> CTRL1
154          * DISP  -> CTRL2
155          * 0     -> CTRL3
156          */
157         rcar_lvds_write(lvds, LVDCTRCR, LVDCTRCR_CTR3SEL_ZERO |
158                         LVDCTRCR_CTR2SEL_DISP | LVDCTRCR_CTR1SEL_VSYNC |
159                         LVDCTRCR_CTR0SEL_HSYNC);
160
161         if (rcar_du_needs(lvds->dev, RCAR_DU_QUIRK_LVDS_LANES))
162                 lvdhcr = LVDCHCR_CHSEL_CH(0, 0) | LVDCHCR_CHSEL_CH(1, 3)
163                        | LVDCHCR_CHSEL_CH(2, 2) | LVDCHCR_CHSEL_CH(3, 1);
164         else
165                 lvdhcr = LVDCHCR_CHSEL_CH(0, 0) | LVDCHCR_CHSEL_CH(1, 1)
166                        | LVDCHCR_CHSEL_CH(2, 2) | LVDCHCR_CHSEL_CH(3, 3);
167
168         rcar_lvds_write(lvds, LVDCHCR, lvdhcr);
169
170         /* Perform generation-specific initialization. */
171         if (lvds->dev->info->gen < 3)
172                 rcar_du_lvdsenc_start_gen2(lvds, rcrtc);
173         else
174                 rcar_du_lvdsenc_start_gen3(lvds, rcrtc);
175
176         lvds->enabled = true;
177
178         return 0;
179 }
180
181 static void rcar_du_lvdsenc_stop(struct rcar_du_lvdsenc *lvds)
182 {
183         if (!lvds->enabled)
184                 return;
185
186         rcar_lvds_write(lvds, LVDCR0, 0);
187         rcar_lvds_write(lvds, LVDCR1, 0);
188
189         clk_disable_unprepare(lvds->clock);
190
191         lvds->enabled = false;
192 }
193
194 int rcar_du_lvdsenc_enable(struct rcar_du_lvdsenc *lvds, struct drm_crtc *crtc,
195                            bool enable)
196 {
197         if (!enable) {
198                 rcar_du_lvdsenc_stop(lvds);
199                 return 0;
200         } else if (crtc) {
201                 struct rcar_du_crtc *rcrtc = to_rcar_crtc(crtc);
202                 return rcar_du_lvdsenc_start(lvds, rcrtc);
203         } else
204                 return -EINVAL;
205 }
206
207 void rcar_du_lvdsenc_atomic_check(struct rcar_du_lvdsenc *lvds,
208                                   struct drm_display_mode *mode)
209 {
210         struct rcar_du_device *rcdu = lvds->dev;
211
212         /*
213          * The internal LVDS encoder has a restricted clock frequency operating
214          * range (30MHz to 150MHz on Gen2, 25.175MHz to 148.5MHz on Gen3). Clamp
215          * the clock accordingly.
216          */
217         if (rcdu->info->gen < 3)
218                 mode->clock = clamp(mode->clock, 30000, 150000);
219         else
220                 mode->clock = clamp(mode->clock, 25175, 148500);
221 }
222
223 void rcar_du_lvdsenc_set_mode(struct rcar_du_lvdsenc *lvds,
224                               enum rcar_lvds_mode mode)
225 {
226         lvds->mode = mode;
227 }
228
229 static int rcar_du_lvdsenc_get_resources(struct rcar_du_lvdsenc *lvds,
230                                          struct platform_device *pdev)
231 {
232         struct resource *mem;
233         char name[7];
234
235         sprintf(name, "lvds.%u", lvds->index);
236
237         mem = platform_get_resource_byname(pdev, IORESOURCE_MEM, name);
238         lvds->mmio = devm_ioremap_resource(&pdev->dev, mem);
239         if (IS_ERR(lvds->mmio))
240                 return PTR_ERR(lvds->mmio);
241
242         lvds->clock = devm_clk_get(&pdev->dev, name);
243         if (IS_ERR(lvds->clock)) {
244                 dev_err(&pdev->dev, "failed to get clock for %s\n", name);
245                 return PTR_ERR(lvds->clock);
246         }
247
248         return 0;
249 }
250
251 int rcar_du_lvdsenc_init(struct rcar_du_device *rcdu)
252 {
253         struct platform_device *pdev = to_platform_device(rcdu->dev);
254         struct rcar_du_lvdsenc *lvds;
255         unsigned int i;
256         int ret;
257
258         for (i = 0; i < rcdu->info->num_lvds; ++i) {
259                 lvds = devm_kzalloc(&pdev->dev, sizeof(*lvds), GFP_KERNEL);
260                 if (lvds == NULL)
261                         return -ENOMEM;
262
263                 lvds->dev = rcdu;
264                 lvds->index = i;
265                 lvds->input = i ? RCAR_LVDS_INPUT_DU1 : RCAR_LVDS_INPUT_DU0;
266                 lvds->enabled = false;
267
268                 ret = rcar_du_lvdsenc_get_resources(lvds, pdev);
269                 if (ret < 0)
270                         return ret;
271
272                 rcdu->lvds[i] = lvds;
273         }
274
275         return 0;
276 }