Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris...
[sfrench/cifs-2.6.git] / drivers / media / platform / blackfin / ppi.c
1 /*
2  * ppi.c Analog Devices Parallel Peripheral Interface driver
3  *
4  * Copyright (c) 2011 Analog Devices Inc.
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License version 2 as
8  * published by the Free Software Foundation.
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  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18  */
19
20 #include <linux/slab.h>
21
22 #include <asm/bfin_ppi.h>
23 #include <asm/blackfin.h>
24 #include <asm/cacheflush.h>
25 #include <asm/dma.h>
26 #include <asm/portmux.h>
27
28 #include <media/blackfin/ppi.h>
29
30 static int ppi_attach_irq(struct ppi_if *ppi, irq_handler_t handler);
31 static void ppi_detach_irq(struct ppi_if *ppi);
32 static int ppi_start(struct ppi_if *ppi);
33 static int ppi_stop(struct ppi_if *ppi);
34 static int ppi_set_params(struct ppi_if *ppi, struct ppi_params *params);
35 static void ppi_update_addr(struct ppi_if *ppi, unsigned long addr);
36
37 static const struct ppi_ops ppi_ops = {
38         .attach_irq = ppi_attach_irq,
39         .detach_irq = ppi_detach_irq,
40         .start = ppi_start,
41         .stop = ppi_stop,
42         .set_params = ppi_set_params,
43         .update_addr = ppi_update_addr,
44 };
45
46 static irqreturn_t ppi_irq_err(int irq, void *dev_id)
47 {
48         struct ppi_if *ppi = dev_id;
49         const struct ppi_info *info = ppi->info;
50
51         switch (info->type) {
52         case PPI_TYPE_PPI:
53         {
54                 struct bfin_ppi_regs *reg = info->base;
55                 unsigned short status;
56
57                 /* register on bf561 is cleared when read 
58                  * others are W1C
59                  */
60                 status = bfin_read16(&reg->status);
61                 bfin_write16(&reg->status, 0xff00);
62                 break;
63         }
64         case PPI_TYPE_EPPI:
65         {
66                 struct bfin_eppi_regs *reg = info->base;
67                 bfin_write16(&reg->status, 0xffff);
68                 break;
69         }
70         default:
71                 break;
72         }
73
74         return IRQ_HANDLED;
75 }
76
77 static int ppi_attach_irq(struct ppi_if *ppi, irq_handler_t handler)
78 {
79         const struct ppi_info *info = ppi->info;
80         int ret;
81
82         ret = request_dma(info->dma_ch, "PPI_DMA");
83
84         if (ret) {
85                 pr_err("Unable to allocate DMA channel for PPI\n");
86                 return ret;
87         }
88         set_dma_callback(info->dma_ch, handler, ppi);
89
90         if (ppi->err_int) {
91                 ret = request_irq(info->irq_err, ppi_irq_err, 0, "PPI ERROR", ppi);
92                 if (ret) {
93                         pr_err("Unable to allocate IRQ for PPI\n");
94                         free_dma(info->dma_ch);
95                 }
96         }
97         return ret;
98 }
99
100 static void ppi_detach_irq(struct ppi_if *ppi)
101 {
102         const struct ppi_info *info = ppi->info;
103
104         if (ppi->err_int)
105                 free_irq(info->irq_err, ppi);
106         free_dma(info->dma_ch);
107 }
108
109 static int ppi_start(struct ppi_if *ppi)
110 {
111         const struct ppi_info *info = ppi->info;
112
113         /* enable DMA */
114         enable_dma(info->dma_ch);
115
116         /* enable PPI */
117         ppi->ppi_control |= PORT_EN;
118         switch (info->type) {
119         case PPI_TYPE_PPI:
120         {
121                 struct bfin_ppi_regs *reg = info->base;
122                 bfin_write16(&reg->control, ppi->ppi_control);
123                 break;
124         }
125         case PPI_TYPE_EPPI:
126         {
127                 struct bfin_eppi_regs *reg = info->base;
128                 bfin_write32(&reg->control, ppi->ppi_control);
129                 break;
130         }
131         default:
132                 return -EINVAL;
133         }
134
135         SSYNC();
136         return 0;
137 }
138
139 static int ppi_stop(struct ppi_if *ppi)
140 {
141         const struct ppi_info *info = ppi->info;
142
143         /* disable PPI */
144         ppi->ppi_control &= ~PORT_EN;
145         switch (info->type) {
146         case PPI_TYPE_PPI:
147         {
148                 struct bfin_ppi_regs *reg = info->base;
149                 bfin_write16(&reg->control, ppi->ppi_control);
150                 break;
151         }
152         case PPI_TYPE_EPPI:
153         {
154                 struct bfin_eppi_regs *reg = info->base;
155                 bfin_write32(&reg->control, ppi->ppi_control);
156                 break;
157         }
158         default:
159                 return -EINVAL;
160         }
161
162         /* disable DMA */
163         clear_dma_irqstat(info->dma_ch);
164         disable_dma(info->dma_ch);
165
166         SSYNC();
167         return 0;
168 }
169
170 static int ppi_set_params(struct ppi_if *ppi, struct ppi_params *params)
171 {
172         const struct ppi_info *info = ppi->info;
173         int dma32 = 0;
174         int dma_config, bytes_per_line, lines_per_frame;
175
176         bytes_per_line = params->width * params->bpp / 8;
177         lines_per_frame = params->height;
178         if (params->int_mask == 0xFFFFFFFF)
179                 ppi->err_int = false;
180         else
181                 ppi->err_int = true;
182
183         dma_config = (DMA_FLOW_STOP | WNR | RESTART | DMA2D | DI_EN);
184         ppi->ppi_control = params->ppi_control & ~PORT_EN;
185         switch (info->type) {
186         case PPI_TYPE_PPI:
187         {
188                 struct bfin_ppi_regs *reg = info->base;
189
190                 if (params->ppi_control & DMA32)
191                         dma32 = 1;
192
193                 bfin_write16(&reg->control, ppi->ppi_control);
194                 bfin_write16(&reg->count, bytes_per_line - 1);
195                 bfin_write16(&reg->frame, lines_per_frame);
196                 break;
197         }
198         case PPI_TYPE_EPPI:
199         {
200                 struct bfin_eppi_regs *reg = info->base;
201
202                 if ((params->ppi_control & PACK_EN)
203                         || (params->ppi_control & 0x38000) > DLEN_16)
204                         dma32 = 1;
205
206                 bfin_write32(&reg->control, ppi->ppi_control);
207                 bfin_write16(&reg->line, bytes_per_line + params->blank_clocks);
208                 bfin_write16(&reg->frame, lines_per_frame);
209                 bfin_write16(&reg->hdelay, 0);
210                 bfin_write16(&reg->vdelay, 0);
211                 bfin_write16(&reg->hcount, bytes_per_line);
212                 bfin_write16(&reg->vcount, lines_per_frame);
213                 break;
214         }
215         default:
216                 return -EINVAL;
217         }
218
219         if (dma32) {
220                 dma_config |= WDSIZE_32;
221                 set_dma_x_count(info->dma_ch, bytes_per_line >> 2);
222                 set_dma_x_modify(info->dma_ch, 4);
223                 set_dma_y_modify(info->dma_ch, 4);
224         } else {
225                 dma_config |= WDSIZE_16;
226                 set_dma_x_count(info->dma_ch, bytes_per_line >> 1);
227                 set_dma_x_modify(info->dma_ch, 2);
228                 set_dma_y_modify(info->dma_ch, 2);
229         }
230         set_dma_y_count(info->dma_ch, lines_per_frame);
231         set_dma_config(info->dma_ch, dma_config);
232
233         SSYNC();
234         return 0;
235 }
236
237 static void ppi_update_addr(struct ppi_if *ppi, unsigned long addr)
238 {
239         set_dma_start_addr(ppi->info->dma_ch, addr);
240 }
241
242 struct ppi_if *ppi_create_instance(const struct ppi_info *info)
243 {
244         struct ppi_if *ppi;
245
246         if (!info || !info->pin_req)
247                 return NULL;
248
249         if (peripheral_request_list(info->pin_req, KBUILD_MODNAME)) {
250                 pr_err("request peripheral failed\n");
251                 return NULL;
252         }
253
254         ppi = kzalloc(sizeof(*ppi), GFP_KERNEL);
255         if (!ppi) {
256                 peripheral_free_list(info->pin_req);
257                 pr_err("unable to allocate memory for ppi handle\n");
258                 return NULL;
259         }
260         ppi->ops = &ppi_ops;
261         ppi->info = info;
262
263         pr_info("ppi probe success\n");
264         return ppi;
265 }
266
267 void ppi_delete_instance(struct ppi_if *ppi)
268 {
269         peripheral_free_list(ppi->info->pin_req);
270         kfree(ppi);
271 }