]> rtime.felk.cvut.cz Git - sojka/nv-tegra/linux-3.10.git/blob - drivers/video/tegra/dc/mipi_cal.c
tegra: dsi: Deselect CSI pads during calibration
[sojka/nv-tegra/linux-3.10.git] / drivers / video / tegra / dc / mipi_cal.c
1 /*
2  * drivers/video/tegra/dc/mipi_cal.c
3  *
4  * Copyright (c) 2012-2015, NVIDIA CORPORATION, All rights reserved.
5  *
6  * This software is licensed under the terms of the GNU General Public
7  * License version 2, as published by the Free Software Foundation, and
8  * may be copied, distributed, and modified under those terms.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  */
16
17 #include <linux/debugfs.h>
18 #include <linux/ioport.h>
19 #include <linux/gfp.h>
20 #include <linux/export.h>
21 #include "dc_priv.h"
22 #include "mipi_cal.h"
23 #include "mipi_cal_regs.h"
24 #include "dsi.h"
25 #include <linux/of_address.h>
26
27 #include "../../../../arch/arm/mach-tegra/iomap.h"
28
29 #ifdef CONFIG_DEBUG_FS
30 static int dbg_dsi_mipi_show(struct seq_file *s, void *unused)
31 {
32         struct tegra_mipi_cal *mipi_cal = s->private;
33         unsigned long i = 0;
34         u32 col = 0;
35
36         /* If gated quitely return */
37         if (!tegra_dc_is_powered(mipi_cal->dc))
38                 return 0;
39
40         BUG_ON(IS_ERR_OR_NULL(mipi_cal));
41         mutex_lock(&mipi_cal->lock);
42         tegra_mipi_cal_clk_enable(mipi_cal);
43
44         /* mem dd dump */
45         for (col = 0, i = 0; i <= MIPI_VALID_REG_LIMIT ; i += 4) {
46                 if (col == 0)
47                         seq_printf(s, "%08lX:", TEGRA_MIPI_CAL_BASE + i);
48                 seq_printf(s, "%c%08lX", col == 2 ? '-' : ' ',
49                         tegra_mipi_cal_read(mipi_cal, i));
50                 if (col == 3) {
51                         seq_printf(s, "\n");
52                         col = 0;
53                 } else
54                         col++;
55         }
56         seq_printf(s, "\n");
57
58         tegra_mipi_cal_clk_disable(mipi_cal);
59         mutex_unlock(&mipi_cal->lock);
60         return 0;
61 }
62
63 static int dbg_dsi_mipi_open(struct inode *inode, struct file *file)
64 {
65         return single_open(file, dbg_dsi_mipi_show, inode->i_private);
66 }
67
68 static const struct file_operations dbg_fops = {
69         .open           = dbg_dsi_mipi_open,
70         .read           = seq_read,
71         .llseek         = seq_lseek,
72         .release        = single_release,
73 };
74
75 static struct dentry *mipidir;
76
77 static void dbg_dsi_mipi_dir_create(struct tegra_mipi_cal *mipi_cal)
78 {
79         struct dentry *retval;
80
81         mipidir = debugfs_create_dir("tegra_mipi_cal", NULL);
82         if (!mipidir)
83                 return;
84         retval = debugfs_create_file("regs", S_IRUGO, mipidir, mipi_cal,
85                 &dbg_fops);
86         if (!retval)
87                 goto free_out;
88         return;
89 free_out:
90         debugfs_remove_recursive(mipidir);
91         mipidir = NULL;
92         return;
93 }
94 #else
95 static inline void dbg_dsi_mipi_dir_create(struct tegra_mipi_cal *mipi_cal)
96 { }
97 #endif
98
99 int tegra_mipi_cal_init_hw(struct tegra_mipi_cal *mipi_cal)
100 {
101         BUG_ON(IS_ERR_OR_NULL(mipi_cal));
102
103         mutex_lock(&mipi_cal->lock);
104
105         tegra_mipi_cal_clk_enable(mipi_cal);
106
107         /* Clear MIPI cal status register */
108         tegra_mipi_cal_write(mipi_cal,
109                         MIPI_AUTO_CAL_DONE_DSID(0x1) |
110                         MIPI_AUTO_CAL_DONE_DSIC(0x1) |
111                         MIPI_AUTO_CAL_DONE_DSIB(0x1) |
112                         MIPI_AUTO_CAL_DONE_DSIA(0x1) |
113                         MIPI_AUTO_CAL_DONE_CSIE(0x1) |
114                         MIPI_AUTO_CAL_DONE_CSID(0x1) |
115                         MIPI_AUTO_CAL_DONE_CSIC(0x1) |
116                         MIPI_AUTO_CAL_DONE_CSIB(0x1) |
117                         MIPI_AUTO_CAL_DONE_CSIA(0x1) |
118                         MIPI_AUTO_CAL_DONE(0x1) |
119                         MIPI_CAL_DRIV_DN_ADJ(0x0) |
120                         MIPI_CAL_DRIV_UP_ADJ(0x0) |
121                         MIPI_CAL_TERMADJ(0x0) |
122                         MIPI_CAL_ACTIVE(0x0),
123                 MIPI_CAL_CIL_MIPI_CAL_STATUS_0);
124
125         tegra_mipi_cal_clk_disable(mipi_cal);
126         mutex_unlock(&mipi_cal->lock);
127
128         return 0;
129 }
130 EXPORT_SYMBOL(tegra_mipi_cal_init_hw);
131
132 struct tegra_mipi_cal *tegra_mipi_cal_init_sw(struct tegra_dc *dc)
133 {
134         struct tegra_mipi_cal *mipi_cal;
135         struct resource *res;
136         struct resource mipi_res;
137         struct resource *base_res;
138         struct clk *clk;
139         struct clk *fixed_clk;
140         void __iomem *base;
141         int err = 0;
142 #ifdef CONFIG_USE_OF
143         struct device_node *np_mipi_cal =
144                 of_find_node_by_path("/mipical");
145 #else
146         struct device_node *np_mipi_cal = NULL;
147 #endif
148         mipi_cal = devm_kzalloc(&dc->ndev->dev, sizeof(*mipi_cal), GFP_KERNEL);
149         if (!mipi_cal) {
150                 dev_err(&dc->ndev->dev, "mipi_cal: memory allocation fail\n");
151                 err = -ENOMEM;
152                 goto fail;
153         }
154
155         if (np_mipi_cal && of_device_is_available(np_mipi_cal)) {
156                         of_address_to_resource(
157                                 np_mipi_cal, 0, &mipi_res);
158                         res = &mipi_res;
159         } else {
160                 res = platform_get_resource_byname(dc->ndev,
161                                 IORESOURCE_MEM, "mipi_cal");
162         }
163         if (!res) {
164                 dev_err(&dc->ndev->dev, "mipi_cal: no entry in resource\n");
165                 err = -ENOENT;
166                 goto fail_free_mipi_cal;
167         }
168
169         base_res = devm_request_mem_region(&dc->ndev->dev, res->start,
170                 resource_size(res), dc->ndev->name);
171         base = devm_ioremap(&dc->ndev->dev, res->start,
172                         resource_size(res));
173         if (!base) {
174                 dev_err(&dc->ndev->dev, "mipi_cal: bus to virtual mapping failed\n");
175                 err = -EBUSY;
176                 goto fail_free_res;
177         }
178
179         clk = clk_get_sys("mipi-cal", NULL);
180         if (IS_ERR_OR_NULL(clk)) {
181                 dev_err(&dc->ndev->dev, "mipi_cal: clk get failed\n");
182                 err = PTR_ERR(clk);
183                 goto fail_free_map;
184         }
185         fixed_clk = clk_get_sys("mipi-cal-fixed", NULL);
186         if (IS_ERR_OR_NULL(fixed_clk)) {
187                 dev_err(&dc->ndev->dev, "mipi_cal: fixed clk get failed\n");
188                 err = PTR_ERR(fixed_clk);
189                 goto fail_free_map;
190         }
191
192         mutex_init(&mipi_cal->lock);
193         mipi_cal->dc = dc;
194         mipi_cal->res = res;
195         mipi_cal->base = base;
196         mipi_cal->base_res = base_res;
197         mipi_cal->clk = clk;
198         mipi_cal->fixed_clk = fixed_clk;
199         dbg_dsi_mipi_dir_create(mipi_cal);
200         return mipi_cal;
201
202 fail_free_map:
203         devm_iounmap(&dc->ndev->dev, base);
204         devm_release_mem_region(&dc->ndev->dev,
205                 res->start, resource_size(res));
206 fail_free_res:
207         if (!np_mipi_cal || !of_device_is_available(np_mipi_cal))
208                 release_resource(res);
209 fail_free_mipi_cal:
210         devm_kfree(&dc->ndev->dev, mipi_cal);
211 fail:
212         return ERR_PTR(err);
213 }
214 EXPORT_SYMBOL(tegra_mipi_cal_init_sw);
215
216 void tegra_mipi_cal_destroy(struct tegra_dc *dc)
217 {
218 #ifdef CONFIG_USE_OF
219         struct device_node *np_mipi_cal =
220                 of_find_node_by_path("/mipical");
221 #else
222         struct device_node *np_mipi_cal = NULL;
223 #endif
224         struct tegra_mipi_cal *mipi_cal =
225                 ((struct tegra_dc_dsi_data *)
226                 (tegra_dc_get_outdata(dc)))->mipi_cal;
227
228         BUG_ON(IS_ERR_OR_NULL(mipi_cal));
229
230         mutex_lock(&mipi_cal->lock);
231
232         clk_put(mipi_cal->clk);
233         devm_iounmap(&dc->ndev->dev, mipi_cal->base);
234         devm_release_mem_region(&dc->ndev->dev,
235                 mipi_cal->res->start,
236                 resource_size(mipi_cal->res));
237
238         if (!np_mipi_cal || !of_device_is_available(np_mipi_cal))
239                 release_resource(mipi_cal->res);
240
241         mutex_unlock(&mipi_cal->lock);
242
243         mutex_destroy(&mipi_cal->lock);
244         devm_kfree(&dc->ndev->dev, mipi_cal);
245 #ifdef CONFIG_DEBUG_FS
246         debugfs_remove_recursive(mipidir);
247 #endif
248 }
249 EXPORT_SYMBOL(tegra_mipi_cal_destroy);
250