aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHans Verkuil <hans.verkuil@cisco.com>2013-03-25 04:35:17 -0400
committerMauro Carvalho Chehab <mchehab@redhat.com>2013-03-25 07:25:07 -0400
commitdcae5dacbce518513abf7776cb450b7bd95d722b (patch)
tree2e0d8d5376ca5655b38eae279b6112efdca7cc1d
parentc535cc6c714bd21b3afad35baa926b3b9eb51361 (diff)
[media] solo6x10: sync to latest code from Bluecherry's git repo
Synced to commit e9815ac5503ae60cfbf6ff8037035de8f62e2846 from branch next in git repository https://github.com/bluecherrydvr/solo6x10.git Only removed some code under #if LINUX_VERSION_CODE < some-kernel-version, renamed the driver back to solo6x10 from solo6x10-edge, removed the unnecessary compat.h header and kept the slab.h includes. Otherwise the code is identical. Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com> Signed-off-by: Ismael Luceno <ismael.luceno@corp.bluecherry.net> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
-rw-r--r--drivers/staging/media/solo6x10/Makefile2
-rw-r--r--drivers/staging/media/solo6x10/TODO33
-rw-r--r--drivers/staging/media/solo6x10/core.c576
-rw-r--r--drivers/staging/media/solo6x10/disp.c127
-rw-r--r--drivers/staging/media/solo6x10/eeprom.c154
-rw-r--r--drivers/staging/media/solo6x10/enc.c239
-rw-r--r--drivers/staging/media/solo6x10/g723.c92
-rw-r--r--drivers/staging/media/solo6x10/gpio.c13
-rw-r--r--drivers/staging/media/solo6x10/i2c.c26
-rw-r--r--drivers/staging/media/solo6x10/offsets.h79
-rw-r--r--drivers/staging/media/solo6x10/osd-font.h154
-rw-r--r--drivers/staging/media/solo6x10/p2m.c393
-rw-r--r--drivers/staging/media/solo6x10/registers.h86
-rw-r--r--drivers/staging/media/solo6x10/solo6x10-jpeg.h94
-rw-r--r--drivers/staging/media/solo6x10/solo6x10.h198
-rw-r--r--drivers/staging/media/solo6x10/tw28.c171
-rw-r--r--drivers/staging/media/solo6x10/tw28.h11
-rw-r--r--drivers/staging/media/solo6x10/v4l2-enc.c1370
-rw-r--r--drivers/staging/media/solo6x10/v4l2.c290
19 files changed, 2376 insertions, 1732 deletions
diff --git a/drivers/staging/media/solo6x10/Makefile b/drivers/staging/media/solo6x10/Makefile
index 337e38c3a0f0..9bbde291d6a3 100644
--- a/drivers/staging/media/solo6x10/Makefile
+++ b/drivers/staging/media/solo6x10/Makefile
@@ -1,3 +1,3 @@
1solo6x10-y := core.o i2c.o p2m.o v4l2.o tw28.o gpio.o disp.o enc.o v4l2-enc.o g723.o 1solo6x10-y := core.o i2c.o p2m.o v4l2.o tw28.o gpio.o disp.o enc.o v4l2-enc.o g723.o eeprom.o
2 2
3obj-$(CONFIG_SOLO6X10) += solo6x10.o 3obj-$(CONFIG_SOLO6X10) += solo6x10.o
diff --git a/drivers/staging/media/solo6x10/TODO b/drivers/staging/media/solo6x10/TODO
index d09dd03fafba..7b8db75b1acb 100644
--- a/drivers/staging/media/solo6x10/TODO
+++ b/drivers/staging/media/solo6x10/TODO
@@ -1,24 +1,15 @@
1TODO (staging => main): 1- batch up desc requests for more efficient use of p2m?
2 2- encoder on/off controls
3 * Motion detection flags need to be moved to v4l2 3- mpeg cid bitrate mode (vbr/cbr)
4 * Some private CIDs need to be moved to v4l2 4- mpeg cid bitrate/bitrate-peak
5 5- mpeg encode of user data
6TODO (general): 6- mpeg decode of user data
7 7- implement CID controls for mozaic areas
8 * encoder on/off controls 8
9 * mpeg cid bitrate mode (vbr/cbr) 9- sound
10 * mpeg cid bitrate/bitrate-peak 10 - implement playback via external sound jack
11 * mpeg encode of user data 11 - implement loopback of external sound jack with incoming audio?
12 * mpeg decode of user data 12 - implement pause/resume (make use of in bc-server)
13 * switch between 4 frames/irq to 1 when using mjpeg (and then back
14 when not)
15 * implement a CID control for motion areas/thresholds
16 * implement CID controls for mozaic areas
17 * allow for higher level of interval (for < 1 fps)
18 * sound:
19 - implement playback via external sound jack
20 - implement loopback of external sound jack with incoming audio?
21 - implement pause/resume
22 13
23Please send patches to the linux media list <linux-media@vger.kernel.org> and 14Please send patches to the linux media list <linux-media@vger.kernel.org> and
24Cc Ismael Luceno <ismael.luceno@corp.bluecherry.net>. 15Cc Ismael Luceno <ismael.luceno@corp.bluecherry.net>.
diff --git a/drivers/staging/media/solo6x10/core.c b/drivers/staging/media/solo6x10/core.c
index fd83d6d028bf..75d98cc61c40 100644
--- a/drivers/staging/media/solo6x10/core.c
+++ b/drivers/staging/media/solo6x10/core.c
@@ -1,6 +1,11 @@
1/* 1/*
2 * Copyright (C) 2010 Bluecherry, LLC www.bluecherrydvr.com 2 * Copyright (C) 2010-2013 Bluecherry, LLC <http://www.bluecherrydvr.com>
3 * Copyright (C) 2010 Ben Collins <bcollins@bluecherry.net> 3 *
4 * Original author:
5 * Ben Collins <bcollins@ubuntu.com>
6 *
7 * Additional work by:
8 * John Brooks <john.brooks@bluecherry.net>
4 * 9 *
5 * This program is free software; you can redistribute it and/or modify 10 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by 11 * it under the terms of the GNU General Public License as published by
@@ -21,29 +26,79 @@
21#include <linux/module.h> 26#include <linux/module.h>
22#include <linux/pci.h> 27#include <linux/pci.h>
23#include <linux/interrupt.h> 28#include <linux/interrupt.h>
24#include <linux/slab.h>
25#include <linux/videodev2.h> 29#include <linux/videodev2.h>
30#include <linux/delay.h>
31#include <linux/sysfs.h>
32#include <linux/ktime.h>
33#include <linux/slab.h>
34
26#include "solo6x10.h" 35#include "solo6x10.h"
27#include "tw28.h" 36#include "tw28.h"
28 37
29MODULE_DESCRIPTION("Softlogic 6x10 MP4/H.264 Encoder/Decoder V4L2/ALSA Driver"); 38MODULE_DESCRIPTION("Softlogic 6x10 MPEG4/H.264/G.723 CODEC V4L2/ALSA Driver");
30MODULE_AUTHOR("Ben Collins <bcollins@bluecherry.net>"); 39MODULE_AUTHOR("Bluecherry <maintainers@bluecherrydvr.com>");
31MODULE_VERSION(SOLO6X10_VERSION); 40MODULE_VERSION(SOLO6X10_VERSION);
32MODULE_LICENSE("GPL"); 41MODULE_LICENSE("GPL");
33 42
34void solo_irq_on(struct solo_dev *solo_dev, u32 mask) 43unsigned video_nr = -1;
44module_param(video_nr, uint, 0644);
45MODULE_PARM_DESC(video_nr, "videoX start number, -1 is autodetect (default)");
46
47static int full_eeprom; /* default is only top 64B */
48module_param(full_eeprom, uint, 0644);
49MODULE_PARM_DESC(full_eeprom, "Allow access to full 128B EEPROM (dangerous)");
50
51
52static void solo_set_time(struct solo_dev *solo_dev)
35{ 53{
36 solo_dev->irq_mask |= mask; 54 struct timespec ts;
37 solo_reg_write(solo_dev, SOLO_IRQ_ENABLE, solo_dev->irq_mask); 55
56 ktime_get_ts(&ts);
57
58 solo_reg_write(solo_dev, SOLO_TIMER_SEC, ts.tv_sec);
59 solo_reg_write(solo_dev, SOLO_TIMER_USEC, ts.tv_nsec / NSEC_PER_USEC);
38} 60}
39 61
40void solo_irq_off(struct solo_dev *solo_dev, u32 mask) 62static void solo_timer_sync(struct solo_dev *solo_dev)
41{ 63{
42 solo_dev->irq_mask &= ~mask; 64 u32 sec, usec;
43 solo_reg_write(solo_dev, SOLO_IRQ_ENABLE, solo_dev->irq_mask); 65 struct timespec ts;
66 long diff;
67
68 if (solo_dev->type != SOLO_DEV_6110)
69 return;
70
71 if (++solo_dev->time_sync < 60)
72 return;
73
74 solo_dev->time_sync = 0;
75
76 sec = solo_reg_read(solo_dev, SOLO_TIMER_SEC);
77 usec = solo_reg_read(solo_dev, SOLO_TIMER_USEC);
78
79 ktime_get_ts(&ts);
80
81 diff = (long)ts.tv_sec - (long)sec;
82 diff = (diff * 1000000)
83 + ((long)(ts.tv_nsec / NSEC_PER_USEC) - (long)usec);
84
85 if (diff > 1000 || diff < -1000) {
86 solo_set_time(solo_dev);
87 } else if (diff) {
88 long usec_lsb = solo_dev->usec_lsb;
89
90 usec_lsb -= diff / 4;
91 if (usec_lsb < 0)
92 usec_lsb = 0;
93 else if (usec_lsb > 255)
94 usec_lsb = 255;
95
96 solo_dev->usec_lsb = usec_lsb;
97 solo_reg_write(solo_dev, SOLO_TIMER_USEC_LSB,
98 solo_dev->usec_lsb);
99 }
44} 100}
45 101
46/* XXX We should check the return value of the sub-device ISR's */
47static irqreturn_t solo_isr(int irq, void *data) 102static irqreturn_t solo_isr(int irq, void *data)
48{ 103{
49 struct solo_dev *solo_dev = data; 104 struct solo_dev *solo_dev = data;
@@ -60,11 +115,8 @@ static irqreturn_t solo_isr(int irq, void *data)
60 status &= solo_dev->irq_mask; 115 status &= solo_dev->irq_mask;
61 } 116 }
62 117
63 if (status & SOLO_IRQ_PCI_ERR) { 118 if (status & SOLO_IRQ_PCI_ERR)
64 u32 err = solo_reg_read(solo_dev, SOLO_PCI_ERR); 119 solo_p2m_error_isr(solo_dev);
65 solo_p2m_error_isr(solo_dev, err);
66 solo_reg_write(solo_dev, SOLO_IRQ_STAT, SOLO_IRQ_PCI_ERR);
67 }
68 120
69 for (i = 0; i < SOLO_NR_P2M; i++) 121 for (i = 0; i < SOLO_NR_P2M; i++)
70 if (status & SOLO_IRQ_P2M(i)) 122 if (status & SOLO_IRQ_P2M(i))
@@ -73,12 +125,10 @@ static irqreturn_t solo_isr(int irq, void *data)
73 if (status & SOLO_IRQ_IIC) 125 if (status & SOLO_IRQ_IIC)
74 solo_i2c_isr(solo_dev); 126 solo_i2c_isr(solo_dev);
75 127
76 if (status & SOLO_IRQ_VIDEO_IN) 128 if (status & SOLO_IRQ_VIDEO_IN) {
77 solo_video_in_isr(solo_dev); 129 solo_video_in_isr(solo_dev);
78 130 solo_timer_sync(solo_dev);
79 /* Call this first so enc gets detected flag set */ 131 }
80 if (status & SOLO_IRQ_MOTION)
81 solo_motion_isr(solo_dev);
82 132
83 if (status & SOLO_IRQ_ENCODER) 133 if (status & SOLO_IRQ_ENCODER)
84 solo_enc_v4l2_isr(solo_dev); 134 solo_enc_v4l2_isr(solo_dev);
@@ -86,6 +136,9 @@ static irqreturn_t solo_isr(int irq, void *data)
86 if (status & SOLO_IRQ_G723) 136 if (status & SOLO_IRQ_G723)
87 solo_g723_isr(solo_dev); 137 solo_g723_isr(solo_dev);
88 138
139 /* Clear all interrupts handled */
140 solo_reg_write(solo_dev, SOLO_IRQ_STAT, status);
141
89 return IRQ_HANDLED; 142 return IRQ_HANDLED;
90} 143}
91 144
@@ -96,6 +149,9 @@ static void free_solo_dev(struct solo_dev *solo_dev)
96 if (!solo_dev) 149 if (!solo_dev)
97 return; 150 return;
98 151
152 if (solo_dev->dev.parent)
153 device_unregister(&solo_dev->dev);
154
99 pdev = solo_dev->pdev; 155 pdev = solo_dev->pdev;
100 156
101 /* If we never initialized the PCI device, then nothing else 157 /* If we never initialized the PCI device, then nothing else
@@ -105,21 +161,22 @@ static void free_solo_dev(struct solo_dev *solo_dev)
105 return; 161 return;
106 } 162 }
107 163
108 /* Bring down the sub-devices first */
109 solo_g723_exit(solo_dev);
110 solo_enc_v4l2_exit(solo_dev);
111 solo_enc_exit(solo_dev);
112 solo_v4l2_exit(solo_dev);
113 solo_disp_exit(solo_dev);
114 solo_gpio_exit(solo_dev);
115 solo_p2m_exit(solo_dev);
116 solo_i2c_exit(solo_dev);
117
118 /* Now cleanup the PCI device */
119 if (solo_dev->reg_base) { 164 if (solo_dev->reg_base) {
165 /* Bring down the sub-devices first */
166 solo_g723_exit(solo_dev);
167 solo_enc_v4l2_exit(solo_dev);
168 solo_enc_exit(solo_dev);
169 solo_v4l2_exit(solo_dev);
170 solo_disp_exit(solo_dev);
171 solo_gpio_exit(solo_dev);
172 solo_p2m_exit(solo_dev);
173 solo_i2c_exit(solo_dev);
174
175 /* Now cleanup the PCI device */
120 solo_irq_off(solo_dev, ~0); 176 solo_irq_off(solo_dev, ~0);
121 pci_iounmap(pdev, solo_dev->reg_base); 177 pci_iounmap(pdev, solo_dev->reg_base);
122 free_irq(pdev->irq, solo_dev); 178 if (pdev->irq)
179 free_irq(pdev->irq, solo_dev);
123 } 180 }
124 181
125 pci_release_regions(pdev); 182 pci_release_regions(pdev);
@@ -129,29 +186,346 @@ static void free_solo_dev(struct solo_dev *solo_dev)
129 kfree(solo_dev); 186 kfree(solo_dev);
130} 187}
131 188
132static int solo_pci_probe(struct pci_dev *pdev, 189static ssize_t eeprom_store(struct device *dev, struct device_attribute *attr,
133 const struct pci_device_id *id) 190 const char *buf, size_t count)
191{
192 struct solo_dev *solo_dev =
193 container_of(dev, struct solo_dev, dev);
194 unsigned short *p = (unsigned short *)buf;
195 int i;
196
197 if (count & 0x1)
198 dev_warn(dev, "EEPROM Write not aligned (truncating)\n");
199
200 if (!full_eeprom && count > 64) {
201 dev_warn(dev, "EEPROM Write truncated to 64 bytes\n");
202 count = 64;
203 } else if (full_eeprom && count > 128) {
204 dev_warn(dev, "EEPROM Write truncated to 128 bytes\n");
205 count = 128;
206 }
207
208 solo_eeprom_ewen(solo_dev, 1);
209
210 for (i = full_eeprom ? 0 : 32; i < min((int)(full_eeprom ? 64 : 32),
211 (int)(count / 2)); i++)
212 solo_eeprom_write(solo_dev, i, cpu_to_be16(p[i]));
213
214 solo_eeprom_ewen(solo_dev, 0);
215
216 return count;
217}
218
219static ssize_t eeprom_show(struct device *dev, struct device_attribute *attr,
220 char *buf)
221{
222 struct solo_dev *solo_dev =
223 container_of(dev, struct solo_dev, dev);
224 unsigned short *p = (unsigned short *)buf;
225 int count = (full_eeprom ? 128 : 64);
226 int i;
227
228 for (i = (full_eeprom ? 0 : 32); i < (count / 2); i++)
229 p[i] = be16_to_cpu(solo_eeprom_read(solo_dev, i));
230
231 return count;
232}
233
234static ssize_t video_type_store(struct device *dev,
235 struct device_attribute *attr,
236 const char *buf, size_t count)
237{
238 return -EPERM;
239}
240
241static ssize_t video_type_show(struct device *dev,
242 struct device_attribute *attr,
243 char *buf)
244{
245 struct solo_dev *solo_dev =
246 container_of(dev, struct solo_dev, dev);
247
248 return sprintf(buf, "%s", solo_dev->video_type ==
249 SOLO_VO_FMT_TYPE_NTSC ? "NTSC" : "PAL");
250}
251
252static ssize_t p2m_timeouts_show(struct device *dev,
253 struct device_attribute *attr,
254 char *buf)
255{
256 struct solo_dev *solo_dev =
257 container_of(dev, struct solo_dev, dev);
258
259 return sprintf(buf, "%d\n", solo_dev->p2m_timeouts);
260}
261
262static ssize_t sdram_size_show(struct device *dev,
263 struct device_attribute *attr,
264 char *buf)
265{
266 struct solo_dev *solo_dev =
267 container_of(dev, struct solo_dev, dev);
268
269 return sprintf(buf, "%dMegs\n", solo_dev->sdram_size >> 20);
270}
271
272static ssize_t tw28xx_show(struct device *dev,
273 struct device_attribute *attr,
274 char *buf)
275{
276 struct solo_dev *solo_dev =
277 container_of(dev, struct solo_dev, dev);
278
279 return sprintf(buf, "tw2815[%d] tw2864[%d] tw2865[%d]\n",
280 hweight32(solo_dev->tw2815),
281 hweight32(solo_dev->tw2864),
282 hweight32(solo_dev->tw2865));
283}
284
285static ssize_t input_map_show(struct device *dev,
286 struct device_attribute *attr,
287 char *buf)
288{
289 struct solo_dev *solo_dev =
290 container_of(dev, struct solo_dev, dev);
291 unsigned int val;
292 char *out = buf;
293
294 val = solo_reg_read(solo_dev, SOLO_VI_CH_SWITCH_0);
295 out += sprintf(out, "Channel 0 => Input %d\n", val & 0x1f);
296 out += sprintf(out, "Channel 1 => Input %d\n", (val >> 5) & 0x1f);
297 out += sprintf(out, "Channel 2 => Input %d\n", (val >> 10) & 0x1f);
298 out += sprintf(out, "Channel 3 => Input %d\n", (val >> 15) & 0x1f);
299 out += sprintf(out, "Channel 4 => Input %d\n", (val >> 20) & 0x1f);
300 out += sprintf(out, "Channel 5 => Input %d\n", (val >> 25) & 0x1f);
301
302 val = solo_reg_read(solo_dev, SOLO_VI_CH_SWITCH_1);
303 out += sprintf(out, "Channel 6 => Input %d\n", val & 0x1f);
304 out += sprintf(out, "Channel 7 => Input %d\n", (val >> 5) & 0x1f);
305 out += sprintf(out, "Channel 8 => Input %d\n", (val >> 10) & 0x1f);
306 out += sprintf(out, "Channel 9 => Input %d\n", (val >> 15) & 0x1f);
307 out += sprintf(out, "Channel 10 => Input %d\n", (val >> 20) & 0x1f);
308 out += sprintf(out, "Channel 11 => Input %d\n", (val >> 25) & 0x1f);
309
310 val = solo_reg_read(solo_dev, SOLO_VI_CH_SWITCH_2);
311 out += sprintf(out, "Channel 12 => Input %d\n", val & 0x1f);
312 out += sprintf(out, "Channel 13 => Input %d\n", (val >> 5) & 0x1f);
313 out += sprintf(out, "Channel 14 => Input %d\n", (val >> 10) & 0x1f);
314 out += sprintf(out, "Channel 15 => Input %d\n", (val >> 15) & 0x1f);
315 out += sprintf(out, "Spot Output => Input %d\n", (val >> 20) & 0x1f);
316
317 return out - buf;
318}
319
320static ssize_t p2m_timeout_store(struct device *dev,
321 struct device_attribute *attr,
322 const char *buf, size_t count)
323{
324 struct solo_dev *solo_dev =
325 container_of(dev, struct solo_dev, dev);
326 unsigned long ms;
327
328 int ret = kstrtoul(buf, 10, &ms);
329 if (ret < 0 || ms > 200)
330 return -EINVAL;
331 solo_dev->p2m_jiffies = msecs_to_jiffies(ms);
332
333 return count;
334}
335
336static ssize_t p2m_timeout_show(struct device *dev,
337 struct device_attribute *attr,
338 char *buf)
339{
340 struct solo_dev *solo_dev =
341 container_of(dev, struct solo_dev, dev);
342
343 return sprintf(buf, "%ums\n", jiffies_to_msecs(solo_dev->p2m_jiffies));
344}
345
346static ssize_t intervals_show(struct device *dev,
347 struct device_attribute *attr,
348 char *buf)
349{
350 struct solo_dev *solo_dev =
351 container_of(dev, struct solo_dev, dev);
352 char *out = buf;
353 int fps = solo_dev->fps;
354 int i;
355
356 for (i = 0; i < solo_dev->nr_chans; i++) {
357 out += sprintf(out, "Channel %d: %d/%d (0x%08x)\n",
358 i, solo_dev->v4l2_enc[i]->interval, fps,
359 solo_reg_read(solo_dev, SOLO_CAP_CH_INTV(i)));
360 }
361
362 return out - buf;
363}
364
365static ssize_t sdram_offsets_show(struct device *dev,
366 struct device_attribute *attr,
367 char *buf)
368{
369 struct solo_dev *solo_dev =
370 container_of(dev, struct solo_dev, dev);
371 char *out = buf;
372
373 out += sprintf(out, "DISP: 0x%08x @ 0x%08x\n",
374 SOLO_DISP_EXT_ADDR,
375 SOLO_DISP_EXT_SIZE);
376
377 out += sprintf(out, "EOSD: 0x%08x @ 0x%08x (0x%08x * %d)\n",
378 SOLO_EOSD_EXT_ADDR,
379 SOLO_EOSD_EXT_AREA(solo_dev),
380 SOLO_EOSD_EXT_SIZE(solo_dev),
381 SOLO_EOSD_EXT_AREA(solo_dev) /
382 SOLO_EOSD_EXT_SIZE(solo_dev));
383
384 out += sprintf(out, "MOTI: 0x%08x @ 0x%08x\n",
385 SOLO_MOTION_EXT_ADDR(solo_dev),
386 SOLO_MOTION_EXT_SIZE);
387
388 out += sprintf(out, "G723: 0x%08x @ 0x%08x\n",
389 SOLO_G723_EXT_ADDR(solo_dev),
390 SOLO_G723_EXT_SIZE);
391
392 out += sprintf(out, "CAPT: 0x%08x @ 0x%08x (0x%08x * %d)\n",
393 SOLO_CAP_EXT_ADDR(solo_dev),
394 SOLO_CAP_EXT_SIZE(solo_dev),
395 SOLO_CAP_PAGE_SIZE,
396 SOLO_CAP_EXT_SIZE(solo_dev) / SOLO_CAP_PAGE_SIZE);
397
398 out += sprintf(out, "EREF: 0x%08x @ 0x%08x (0x%08x * %d)\n",
399 SOLO_EREF_EXT_ADDR(solo_dev),
400 SOLO_EREF_EXT_AREA(solo_dev),
401 SOLO_EREF_EXT_SIZE,
402 SOLO_EREF_EXT_AREA(solo_dev) / SOLO_EREF_EXT_SIZE);
403
404 out += sprintf(out, "MPEG: 0x%08x @ 0x%08x\n",
405 SOLO_MP4E_EXT_ADDR(solo_dev),
406 SOLO_MP4E_EXT_SIZE(solo_dev));
407
408 out += sprintf(out, "JPEG: 0x%08x @ 0x%08x\n",
409 SOLO_JPEG_EXT_ADDR(solo_dev),
410 SOLO_JPEG_EXT_SIZE(solo_dev));
411
412 return out - buf;
413}
414
415static ssize_t sdram_show(struct file *file, struct kobject *kobj,
416 struct bin_attribute *a, char *buf,
417 loff_t off, size_t count)
418{
419 struct device *dev = container_of(kobj, struct device, kobj);
420 struct solo_dev *solo_dev =
421 container_of(dev, struct solo_dev, dev);
422 const int size = solo_dev->sdram_size;
423
424 if (off >= size)
425 return 0;
426
427 if (off + count > size)
428 count = size - off;
429
430 if (solo_p2m_dma(solo_dev, 0, buf, off, count, 0, 0))
431 return -EIO;
432
433 return count;
434}
435
436static const struct device_attribute solo_dev_attrs[] = {
437 __ATTR(eeprom, 0640, eeprom_show, eeprom_store),
438 __ATTR(video_type, 0644, video_type_show, video_type_store),
439 __ATTR(p2m_timeout, 0644, p2m_timeout_show, p2m_timeout_store),
440 __ATTR_RO(p2m_timeouts),
441 __ATTR_RO(sdram_size),
442 __ATTR_RO(tw28xx),
443 __ATTR_RO(input_map),
444 __ATTR_RO(intervals),
445 __ATTR_RO(sdram_offsets),
446};
447
448static void solo_device_release(struct device *dev)
449{
450 /* Do nothing */
451}
452
453static int solo_sysfs_init(struct solo_dev *solo_dev)
454{
455 struct bin_attribute *sdram_attr = &solo_dev->sdram_attr;
456 struct device *dev = &solo_dev->dev;
457 const char *driver;
458 int i;
459
460 if (solo_dev->type == SOLO_DEV_6110)
461 driver = "solo6110";
462 else
463 driver = "solo6010";
464
465 dev->release = solo_device_release;
466 dev->parent = &solo_dev->pdev->dev;
467 set_dev_node(dev, dev_to_node(&solo_dev->pdev->dev));
468 dev_set_name(dev, "%s-%d-%d", driver, solo_dev->vfd->num,
469 solo_dev->nr_chans);
470
471 if (device_register(dev)) {
472 dev->parent = NULL;
473 return -ENOMEM;
474 }
475
476 for (i = 0; i < ARRAY_SIZE(solo_dev_attrs); i++) {
477 if (device_create_file(dev, &solo_dev_attrs[i])) {
478 device_unregister(dev);
479 return -ENOMEM;
480 }
481 }
482
483 sdram_attr->attr.name = "sdram";
484 sdram_attr->attr.mode = 0440;
485 sdram_attr->read = sdram_show;
486 sdram_attr->size = solo_dev->sdram_size;
487
488 if (device_create_bin_file(dev, sdram_attr)) {
489 device_unregister(dev);
490 return -ENOMEM;
491 }
492
493 return 0;
494}
495
496static int solo_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
134{ 497{
135 struct solo_dev *solo_dev; 498 struct solo_dev *solo_dev;
136 int ret; 499 int ret;
137 int sdram;
138 u8 chip_id; 500 u8 chip_id;
139 u32 reg;
140 501
141 solo_dev = kzalloc(sizeof(*solo_dev), GFP_KERNEL); 502 solo_dev = kzalloc(sizeof(*solo_dev), GFP_KERNEL);
142 if (solo_dev == NULL) 503 if (solo_dev == NULL)
143 return -ENOMEM; 504 return -ENOMEM;
144 505
506 if (id->driver_data == SOLO_DEV_6010)
507 dev_info(&pdev->dev, "Probing Softlogic 6010\n");
508 else
509 dev_info(&pdev->dev, "Probing Softlogic 6110\n");
510
511 solo_dev->type = id->driver_data;
145 solo_dev->pdev = pdev; 512 solo_dev->pdev = pdev;
146 spin_lock_init(&solo_dev->reg_io_lock); 513 spin_lock_init(&solo_dev->reg_io_lock);
147 pci_set_drvdata(pdev, solo_dev); 514 pci_set_drvdata(pdev, solo_dev);
148 515
516 /* Only for during init */
517 solo_dev->p2m_jiffies = msecs_to_jiffies(100);
518
149 ret = pci_enable_device(pdev); 519 ret = pci_enable_device(pdev);
150 if (ret) 520 if (ret)
151 goto fail_probe; 521 goto fail_probe;
152 522
153 pci_set_master(pdev); 523 pci_set_master(pdev);
154 524
525 /* RETRY/TRDY Timeout disabled */
526 pci_write_config_byte(pdev, 0x40, 0x00);
527 pci_write_config_byte(pdev, 0x41, 0x00);
528
155 ret = pci_request_regions(pdev, SOLO6X10_NAME); 529 ret = pci_request_regions(pdev, SOLO6X10_NAME);
156 if (ret) 530 if (ret)
157 goto fail_probe; 531 goto fail_probe;
@@ -163,7 +537,7 @@ static int solo_pci_probe(struct pci_dev *pdev,
163 } 537 }
164 538
165 chip_id = solo_reg_read(solo_dev, SOLO_CHIP_OPTION) & 539 chip_id = solo_reg_read(solo_dev, SOLO_CHIP_OPTION) &
166 SOLO_CHIP_ID_MASK; 540 SOLO_CHIP_ID_MASK;
167 switch (chip_id) { 541 switch (chip_id) {
168 case 7: 542 case 7:
169 solo_dev->nr_chans = 16; 543 solo_dev->nr_chans = 16;
@@ -174,52 +548,50 @@ static int solo_pci_probe(struct pci_dev *pdev,
174 solo_dev->nr_ext = 2; 548 solo_dev->nr_ext = 2;
175 break; 549 break;
176 default: 550 default:
177 dev_warn(&pdev->dev, "Invalid chip_id 0x%02x, " 551 dev_warn(&pdev->dev, "Invalid chip_id 0x%02x, assuming 4 ch\n",
178 "defaulting to 4 channels\n",
179 chip_id); 552 chip_id);
180 case 5: 553 case 5:
181 solo_dev->nr_chans = 4; 554 solo_dev->nr_chans = 4;
182 solo_dev->nr_ext = 1; 555 solo_dev->nr_ext = 1;
183 } 556 }
184 557
185 solo_dev->flags = id->driver_data;
186
187 /* Disable all interrupts to start */ 558 /* Disable all interrupts to start */
188 solo_irq_off(solo_dev, ~0); 559 solo_irq_off(solo_dev, ~0);
189 560
190 reg = SOLO_SYS_CFG_SDRAM64BIT;
191 /* Initial global settings */ 561 /* Initial global settings */
192 if (!(solo_dev->flags & FLAGS_6110)) 562 if (solo_dev->type == SOLO_DEV_6010) {
193 reg |= SOLO6010_SYS_CFG_INPUTDIV(25) | 563 solo_dev->clock_mhz = 108;
194 SOLO6010_SYS_CFG_FEEDBACKDIV((SOLO_CLOCK_MHZ * 2) - 2) | 564 solo_dev->sys_config = SOLO_SYS_CFG_SDRAM64BIT
195 SOLO6010_SYS_CFG_OUTDIV(3); 565 | SOLO_SYS_CFG_INPUTDIV(25)
196 solo_reg_write(solo_dev, SOLO_SYS_CFG, reg); 566 | SOLO_SYS_CFG_FEEDBACKDIV(solo_dev->clock_mhz * 2 - 2)
197 567 | SOLO_SYS_CFG_OUTDIV(3);
198 if (solo_dev->flags & FLAGS_6110) { 568 solo_reg_write(solo_dev, SOLO_SYS_CFG, solo_dev->sys_config);
199 u32 sys_clock_MHz = SOLO_CLOCK_MHZ; 569 } else {
200 u32 pll_DIVQ; 570 u32 divq, divf;
201 u32 pll_DIVF; 571
202 572 solo_dev->clock_mhz = 135;
203 if (sys_clock_MHz < 125) { 573
204 pll_DIVQ = 3; 574 if (solo_dev->clock_mhz < 125) {
205 pll_DIVF = (sys_clock_MHz * 4) / 3; 575 divq = 3;
576 divf = (solo_dev->clock_mhz * 4) / 3 - 1;
206 } else { 577 } else {
207 pll_DIVQ = 2; 578 divq = 2;
208 pll_DIVF = (sys_clock_MHz * 2) / 3; 579 divf = (solo_dev->clock_mhz * 2) / 3 - 1;
209 } 580 }
210 581
211 solo_reg_write(solo_dev, SOLO6110_PLL_CONFIG, 582 solo_reg_write(solo_dev, SOLO_PLL_CONFIG,
212 SOLO6110_PLL_RANGE_5_10MHZ | 583 (1 << 20) | /* PLL_RANGE */
213 SOLO6110_PLL_DIVR(9) | 584 (8 << 15) | /* PLL_DIVR */
214 SOLO6110_PLL_DIVQ_EXP(pll_DIVQ) | 585 (divq << 12) |
215 SOLO6110_PLL_DIVF(pll_DIVF) | SOLO6110_PLL_FSEN); 586 (divf << 4) |
216 mdelay(1); /* PLL Locking time (1ms) */ 587 (1 << 1) /* PLL_FSEN */);
217 588
218 solo_reg_write(solo_dev, SOLO_DMA_CTRL1, 3 << 8); /* ? */ 589 solo_dev->sys_config = SOLO_SYS_CFG_SDRAM64BIT;
219 } else 590 }
220 solo_reg_write(solo_dev, SOLO_DMA_CTRL1, 1 << 8); /* ? */
221 591
222 solo_reg_write(solo_dev, SOLO_TIMER_CLOCK_NUM, SOLO_CLOCK_MHZ - 1); 592 solo_reg_write(solo_dev, SOLO_SYS_CFG, solo_dev->sys_config);
593 solo_reg_write(solo_dev, SOLO_TIMER_CLOCK_NUM,
594 solo_dev->clock_mhz - 1);
223 595
224 /* PLL locking time of 1ms */ 596 /* PLL locking time of 1ms */
225 mdelay(1); 597 mdelay(1);
@@ -237,14 +609,27 @@ static int solo_pci_probe(struct pci_dev *pdev,
237 goto fail_probe; 609 goto fail_probe;
238 610
239 /* Setup the DMA engine */ 611 /* Setup the DMA engine */
240 sdram = (solo_dev->nr_chans >= 8) ? 2 : 1;
241 solo_reg_write(solo_dev, SOLO_DMA_CTRL, 612 solo_reg_write(solo_dev, SOLO_DMA_CTRL,
242 SOLO_DMA_CTRL_REFRESH_CYCLE(1) | 613 SOLO_DMA_CTRL_REFRESH_CYCLE(1) |
243 SOLO_DMA_CTRL_SDRAM_SIZE(sdram) | 614 SOLO_DMA_CTRL_SDRAM_SIZE(2) |
244 SOLO_DMA_CTRL_SDRAM_CLK_INVERT | 615 SOLO_DMA_CTRL_SDRAM_CLK_INVERT |
245 SOLO_DMA_CTRL_READ_CLK_SELECT | 616 SOLO_DMA_CTRL_READ_CLK_SELECT |
246 SOLO_DMA_CTRL_LATENCY(1)); 617 SOLO_DMA_CTRL_LATENCY(1));
247 618
619 /* Undocumented crap */
620 solo_reg_write(solo_dev, SOLO_DMA_CTRL1,
621 solo_dev->type == SOLO_DEV_6010 ? 0x100 : 0x300);
622
623 if (solo_dev->type != SOLO_DEV_6010) {
624 solo_dev->usec_lsb = 0x3f;
625 solo_set_time(solo_dev);
626 }
627
628 /* Disable watchdog */
629 solo_reg_write(solo_dev, SOLO_WATCHDOG, 0);
630
631 /* Initialize sub components */
632
248 ret = solo_p2m_init(solo_dev); 633 ret = solo_p2m_init(solo_dev);
249 if (ret) 634 if (ret)
250 goto fail_probe; 635 goto fail_probe;
@@ -261,7 +646,7 @@ static int solo_pci_probe(struct pci_dev *pdev,
261 if (ret) 646 if (ret)
262 goto fail_probe; 647 goto fail_probe;
263 648
264 ret = solo_v4l2_init(solo_dev); 649 ret = solo_v4l2_init(solo_dev, video_nr);
265 if (ret) 650 if (ret)
266 goto fail_probe; 651 goto fail_probe;
267 652
@@ -269,7 +654,7 @@ static int solo_pci_probe(struct pci_dev *pdev,
269 if (ret) 654 if (ret)
270 goto fail_probe; 655 goto fail_probe;
271 656
272 ret = solo_enc_v4l2_init(solo_dev); 657 ret = solo_enc_v4l2_init(solo_dev, video_nr);
273 if (ret) 658 if (ret)
274 goto fail_probe; 659 goto fail_probe;
275 660
@@ -277,6 +662,13 @@ static int solo_pci_probe(struct pci_dev *pdev,
277 if (ret) 662 if (ret)
278 goto fail_probe; 663 goto fail_probe;
279 664
665 ret = solo_sysfs_init(solo_dev);
666 if (ret)
667 goto fail_probe;
668
669 /* Now that init is over, set this lower */
670 solo_dev->p2m_jiffies = msecs_to_jiffies(20);
671
280 return 0; 672 return 0;
281 673
282fail_probe: 674fail_probe:
@@ -291,21 +683,31 @@ static void solo_pci_remove(struct pci_dev *pdev)
291 free_solo_dev(solo_dev); 683 free_solo_dev(solo_dev);
292} 684}
293 685
294static struct pci_device_id solo_id_table[] = { 686static DEFINE_PCI_DEVICE_TABLE(solo_id_table) = {
295 /* 6010 based cards */ 687 /* 6010 based cards */
296 {PCI_DEVICE(PCI_VENDOR_ID_SOFTLOGIC, PCI_DEVICE_ID_SOLO6010)}, 688 { PCI_DEVICE(PCI_VENDOR_ID_SOFTLOGIC, PCI_DEVICE_ID_SOLO6010),
297 {PCI_DEVICE(PCI_VENDOR_ID_SOFTLOGIC, PCI_DEVICE_ID_SOLO6110), 689 .driver_data = SOLO_DEV_6010 },
298 .driver_data = FLAGS_6110}, 690 { PCI_DEVICE(PCI_VENDOR_ID_BLUECHERRY, PCI_DEVICE_ID_NEUSOLO_4),
299 {PCI_DEVICE(PCI_VENDOR_ID_BLUECHERRY, PCI_DEVICE_ID_NEUSOLO_4)}, 691 .driver_data = SOLO_DEV_6010 },
300 {PCI_DEVICE(PCI_VENDOR_ID_BLUECHERRY, PCI_DEVICE_ID_NEUSOLO_9)}, 692 { PCI_DEVICE(PCI_VENDOR_ID_BLUECHERRY, PCI_DEVICE_ID_NEUSOLO_9),
301 {PCI_DEVICE(PCI_VENDOR_ID_BLUECHERRY, PCI_DEVICE_ID_NEUSOLO_16)}, 693 .driver_data = SOLO_DEV_6010 },
302 {PCI_DEVICE(PCI_VENDOR_ID_BLUECHERRY, PCI_DEVICE_ID_BC_SOLO_4)}, 694 { PCI_DEVICE(PCI_VENDOR_ID_BLUECHERRY, PCI_DEVICE_ID_NEUSOLO_16),
303 {PCI_DEVICE(PCI_VENDOR_ID_BLUECHERRY, PCI_DEVICE_ID_BC_SOLO_9)}, 695 .driver_data = SOLO_DEV_6010 },
304 {PCI_DEVICE(PCI_VENDOR_ID_BLUECHERRY, PCI_DEVICE_ID_BC_SOLO_16)}, 696 { PCI_DEVICE(PCI_VENDOR_ID_BLUECHERRY, PCI_DEVICE_ID_BC_SOLO_4),
697 .driver_data = SOLO_DEV_6010 },
698 { PCI_DEVICE(PCI_VENDOR_ID_BLUECHERRY, PCI_DEVICE_ID_BC_SOLO_9),
699 .driver_data = SOLO_DEV_6010 },
700 { PCI_DEVICE(PCI_VENDOR_ID_BLUECHERRY, PCI_DEVICE_ID_BC_SOLO_16),
701 .driver_data = SOLO_DEV_6010 },
305 /* 6110 based cards */ 702 /* 6110 based cards */
306 {PCI_DEVICE(PCI_VENDOR_ID_BLUECHERRY, PCI_DEVICE_ID_BC_6110_4)}, 703 { PCI_DEVICE(PCI_VENDOR_ID_SOFTLOGIC, PCI_DEVICE_ID_SOLO6110),
307 {PCI_DEVICE(PCI_VENDOR_ID_BLUECHERRY, PCI_DEVICE_ID_BC_6110_8)}, 704 .driver_data = SOLO_DEV_6110 },
308 {PCI_DEVICE(PCI_VENDOR_ID_BLUECHERRY, PCI_DEVICE_ID_BC_6110_16)}, 705 { PCI_DEVICE(PCI_VENDOR_ID_BLUECHERRY, PCI_DEVICE_ID_BC_6110_4),
706 .driver_data = SOLO_DEV_6110 },
707 { PCI_DEVICE(PCI_VENDOR_ID_BLUECHERRY, PCI_DEVICE_ID_BC_6110_8),
708 .driver_data = SOLO_DEV_6110 },
709 { PCI_DEVICE(PCI_VENDOR_ID_BLUECHERRY, PCI_DEVICE_ID_BC_6110_16),
710 .driver_data = SOLO_DEV_6110 },
309 {0,} 711 {0,}
310}; 712};
311 713
diff --git a/drivers/staging/media/solo6x10/disp.c b/drivers/staging/media/solo6x10/disp.c
index 884c0eb757c4..ddd85e72dd70 100644
--- a/drivers/staging/media/solo6x10/disp.c
+++ b/drivers/staging/media/solo6x10/disp.c
@@ -1,6 +1,11 @@
1/* 1/*
2 * Copyright (C) 2010 Bluecherry, LLC www.bluecherrydvr.com 2 * Copyright (C) 2010-2013 Bluecherry, LLC <http://www.bluecherrydvr.com>
3 * Copyright (C) 2010 Ben Collins <bcollins@bluecherry.net> 3 *
4 * Original author:
5 * Ben Collins <bcollins@ubuntu.com>
6 *
7 * Additional work by:
8 * John Brooks <john.brooks@bluecherry.net>
4 * 9 *
5 * This program is free software; you can redistribute it and/or modify 10 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by 11 * it under the terms of the GNU General Public License as published by
@@ -21,6 +26,7 @@
21#include <linux/module.h> 26#include <linux/module.h>
22#include <linux/videodev2.h> 27#include <linux/videodev2.h>
23#include <media/v4l2-ioctl.h> 28#include <media/v4l2-ioctl.h>
29
24#include "solo6x10.h" 30#include "solo6x10.h"
25 31
26#define SOLO_VCLK_DELAY 3 32#define SOLO_VCLK_DELAY 3
@@ -30,8 +36,8 @@
30#define SOLO_MOT_THRESH_H 64 36#define SOLO_MOT_THRESH_H 64
31#define SOLO_MOT_THRESH_SIZE 8192 37#define SOLO_MOT_THRESH_SIZE 8192
32#define SOLO_MOT_THRESH_REAL (SOLO_MOT_THRESH_W * SOLO_MOT_THRESH_H) 38#define SOLO_MOT_THRESH_REAL (SOLO_MOT_THRESH_W * SOLO_MOT_THRESH_H)
33#define SOLO_MOT_FLAG_SIZE 512 39#define SOLO_MOT_FLAG_SIZE 1024
34#define SOLO_MOT_FLAG_AREA (SOLO_MOT_FLAG_SIZE * 32) 40#define SOLO_MOT_FLAG_AREA (SOLO_MOT_FLAG_SIZE * 16)
35 41
36static unsigned video_type; 42static unsigned video_type;
37module_param(video_type, uint, 0644); 43module_param(video_type, uint, 0644);
@@ -73,7 +79,12 @@ static void solo_vin_config(struct solo_dev *solo_dev)
73 solo_reg_write(solo_dev, SOLO_VI_CH_FORMAT, 79 solo_reg_write(solo_dev, SOLO_VI_CH_FORMAT,
74 SOLO_VI_FD_SEL_MASK(0) | SOLO_VI_PROG_MASK(0)); 80 SOLO_VI_FD_SEL_MASK(0) | SOLO_VI_PROG_MASK(0));
75 81
76 solo_reg_write(solo_dev, SOLO_VI_FMT_CFG, 0); 82 /* On 6110, initialize mozaic darkness stength */
83 if (solo_dev->type == SOLO_DEV_6010)
84 solo_reg_write(solo_dev, SOLO_VI_FMT_CFG, 0);
85 else
86 solo_reg_write(solo_dev, SOLO_VI_FMT_CFG, 16 << 22);
87
77 solo_reg_write(solo_dev, SOLO_VI_PAGE_SW, 2); 88 solo_reg_write(solo_dev, SOLO_VI_PAGE_SW, 2);
78 89
79 if (solo_dev->video_type == SOLO_VO_FMT_TYPE_NTSC) { 90 if (solo_dev->video_type == SOLO_VO_FMT_TYPE_NTSC) {
@@ -97,21 +108,30 @@ static void solo_vin_config(struct solo_dev *solo_dev)
97 SOLO_VI_PB_HSTOP(16 + 720)); 108 SOLO_VI_PB_HSTOP(16 + 720));
98} 109}
99 110
100static void solo_disp_config(struct solo_dev *solo_dev) 111static void solo_vout_config_cursor(struct solo_dev *dev)
112{
113 int i;
114
115 /* Load (blank) cursor bitmap mask (2bpp) */
116 for (i = 0; i < 20; i++)
117 solo_reg_write(dev, SOLO_VO_CURSOR_MASK(i), 0);
118
119 solo_reg_write(dev, SOLO_VO_CURSOR_POS, 0);
120
121 solo_reg_write(dev, SOLO_VO_CURSOR_CLR,
122 (0x80 << 24) | (0x80 << 16) | (0x10 << 8) | 0x80);
123 solo_reg_write(dev, SOLO_VO_CURSOR_CLR2, (0xe0 << 8) | 0x80);
124}
125
126static void solo_vout_config(struct solo_dev *solo_dev)
101{ 127{
102 solo_dev->vout_hstart = 6; 128 solo_dev->vout_hstart = 6;
103 solo_dev->vout_vstart = 8; 129 solo_dev->vout_vstart = 8;
104 130
105 solo_reg_write(solo_dev, SOLO_VO_BORDER_LINE_COLOR,
106 (0xa0 << 24) | (0x88 << 16) | (0xa0 << 8) | 0x88);
107 solo_reg_write(solo_dev, SOLO_VO_BORDER_FILL_COLOR,
108 (0x10 << 24) | (0x8f << 16) | (0x10 << 8) | 0x8f);
109 solo_reg_write(solo_dev, SOLO_VO_BKG_COLOR,
110 (16 << 24) | (128 << 16) | (16 << 8) | 128);
111
112 solo_reg_write(solo_dev, SOLO_VO_FMT_ENC, 131 solo_reg_write(solo_dev, SOLO_VO_FMT_ENC,
113 solo_dev->video_type | 132 solo_dev->video_type |
114 SOLO_VO_USER_COLOR_SET_NAV | 133 SOLO_VO_USER_COLOR_SET_NAV |
134 SOLO_VO_USER_COLOR_SET_NAH |
115 SOLO_VO_NA_COLOR_Y(0) | 135 SOLO_VO_NA_COLOR_Y(0) |
116 SOLO_VO_NA_COLOR_CB(0) | 136 SOLO_VO_NA_COLOR_CB(0) |
117 SOLO_VO_NA_COLOR_CR(0)); 137 SOLO_VO_NA_COLOR_CR(0));
@@ -130,19 +150,31 @@ static void solo_disp_config(struct solo_dev *solo_dev)
130 SOLO_VO_H_LEN(solo_dev->video_hsize) | 150 SOLO_VO_H_LEN(solo_dev->video_hsize) |
131 SOLO_VO_V_LEN(solo_dev->video_vsize)); 151 SOLO_VO_V_LEN(solo_dev->video_vsize));
132 152
133 solo_reg_write(solo_dev, SOLO_VI_WIN_SW, 5); 153 /* Border & background colors */
154 solo_reg_write(solo_dev, SOLO_VO_BORDER_LINE_COLOR,
155 (0xa0 << 24) | (0x88 << 16) | (0xa0 << 8) | 0x88);
156 solo_reg_write(solo_dev, SOLO_VO_BORDER_FILL_COLOR,
157 (0x10 << 24) | (0x8f << 16) | (0x10 << 8) | 0x8f);
158 solo_reg_write(solo_dev, SOLO_VO_BKG_COLOR,
159 (16 << 24) | (128 << 16) | (16 << 8) | 128);
160
161 solo_reg_write(solo_dev, SOLO_VO_DISP_ERASE, SOLO_VO_DISP_ERASE_ON);
162
163 solo_reg_write(solo_dev, SOLO_VI_WIN_SW, 0);
164
165 solo_reg_write(solo_dev, SOLO_VO_ZOOM_CTRL, 0);
166 solo_reg_write(solo_dev, SOLO_VO_FREEZE_CTRL, 0);
134 167
135 solo_reg_write(solo_dev, SOLO_VO_DISP_CTRL, SOLO_VO_DISP_ON | 168 solo_reg_write(solo_dev, SOLO_VO_DISP_CTRL, SOLO_VO_DISP_ON |
136 SOLO_VO_DISP_ERASE_COUNT(8) | 169 SOLO_VO_DISP_ERASE_COUNT(8) |
137 SOLO_VO_DISP_BASE(SOLO_DISP_EXT_ADDR)); 170 SOLO_VO_DISP_BASE(SOLO_DISP_EXT_ADDR));
138 171
139 solo_reg_write(solo_dev, SOLO_VO_DISP_ERASE, SOLO_VO_DISP_ERASE_ON);
140 172
141 /* Enable channels we support */ 173 solo_vout_config_cursor(solo_dev);
142 solo_reg_write(solo_dev, SOLO_VI_CH_ENA, (1 << solo_dev->nr_chans) - 1);
143 174
144 /* Disable the watchdog */ 175 /* Enable channels we support */
145 solo_reg_write(solo_dev, SOLO_WATCHDOG, 0); 176 solo_reg_write(solo_dev, SOLO_VI_CH_ENA,
177 (1 << solo_dev->nr_chans) - 1);
146} 178}
147 179
148static int solo_dma_vin_region(struct solo_dev *solo_dev, u32 off, 180static int solo_dma_vin_region(struct solo_dev *solo_dev, u32 off,
@@ -156,26 +188,53 @@ static int solo_dma_vin_region(struct solo_dev *solo_dev, u32 off,
156 buf[i] = val; 188 buf[i] = val;
157 189
158 for (i = 0; i < reg_size; i += sizeof(buf)) 190 for (i = 0; i < reg_size; i += sizeof(buf))
159 ret |= solo_p2m_dma(solo_dev, SOLO_P2M_DMA_ID_VIN, 1, buf, 191 ret |= solo_p2m_dma(solo_dev, 1, buf,
160 SOLO_MOTION_EXT_ADDR(solo_dev) + off + i, 192 SOLO_MOTION_EXT_ADDR(solo_dev) + off + i,
161 sizeof(buf)); 193 sizeof(buf), 0, 0);
162 194
163 return ret; 195 return ret;
164} 196}
165 197
166void solo_set_motion_threshold(struct solo_dev *solo_dev, u8 ch, u16 val) 198int solo_set_motion_threshold(struct solo_dev *solo_dev, u8 ch, u16 val)
167{ 199{
168 if (ch > solo_dev->nr_chans) 200 if (ch > solo_dev->nr_chans)
169 return; 201 return -EINVAL;
170 202
171 solo_dma_vin_region(solo_dev, SOLO_MOT_FLAG_AREA + 203 return solo_dma_vin_region(solo_dev, SOLO_MOT_FLAG_AREA +
172 (ch * SOLO_MOT_THRESH_SIZE * 2), 204 (ch * SOLO_MOT_THRESH_SIZE * 2),
173 val, SOLO_MOT_THRESH_REAL); 205 val, SOLO_MOT_THRESH_SIZE);
206}
207
208int solo_set_motion_block(struct solo_dev *solo_dev, u8 ch, u16 val,
209 u16 block)
210{
211 u16 buf[64];
212 u32 addr;
213 int re;
214
215 addr = SOLO_MOTION_EXT_ADDR(solo_dev) +
216 SOLO_MOT_FLAG_AREA +
217 (SOLO_MOT_THRESH_SIZE * 2 * ch) +
218 (block * 2);
219
220 /* Read and write only on a 128-byte boundary; 4-byte writes with
221 solo_p2m_dma silently failed. Bluecherry bug #908. */
222 re = solo_p2m_dma(solo_dev, 0, &buf, addr & ~0x7f, sizeof(buf), 0, 0);
223 if (re)
224 return re;
225
226 buf[(addr & 0x7f) / 2] = val;
227
228 re = solo_p2m_dma(solo_dev, 1, &buf, addr & ~0x7f, sizeof(buf), 0, 0);
229 if (re)
230 return re;
231
232 return 0;
174} 233}
175 234
176/* First 8k is motion flag (512 bytes * 16). Following that is an 8k+8k 235/* First 8k is motion flag (512 bytes * 16). Following that is an 8k+8k
177 * threshold and working table for each channel. Atleast that's what the 236 * threshold and working table for each channel. Atleast that's what the
178 * spec says. However, this code (take from rdk) has some mystery 8k 237 * spec says. However, this code (taken from rdk) has some mystery 8k
179 * block right after the flag area, before the first thresh table. */ 238 * block right after the flag area, before the first thresh table. */
180static void solo_motion_config(struct solo_dev *solo_dev) 239static void solo_motion_config(struct solo_dev *solo_dev)
181{ 240{
@@ -188,9 +247,9 @@ static void solo_motion_config(struct solo_dev *solo_dev)
188 247
189 /* Clear working cache table */ 248 /* Clear working cache table */
190 solo_dma_vin_region(solo_dev, SOLO_MOT_FLAG_AREA + 249 solo_dma_vin_region(solo_dev, SOLO_MOT_FLAG_AREA +
191 SOLO_MOT_THRESH_SIZE + 250 (i * SOLO_MOT_THRESH_SIZE * 2) +
192 (i * SOLO_MOT_THRESH_SIZE * 2), 251 SOLO_MOT_THRESH_SIZE, 0x0000,
193 0x0000, SOLO_MOT_THRESH_REAL); 252 SOLO_MOT_THRESH_SIZE);
194 253
195 /* Set default threshold table */ 254 /* Set default threshold table */
196 solo_set_motion_threshold(solo_dev, i, SOLO_DEF_MOT_THRESH); 255 solo_set_motion_threshold(solo_dev, i, SOLO_DEF_MOT_THRESH);
@@ -202,8 +261,8 @@ static void solo_motion_config(struct solo_dev *solo_dev)
202 solo_reg_write(solo_dev, SOLO_VI_MOT_CTRL, 261 solo_reg_write(solo_dev, SOLO_VI_MOT_CTRL,
203 SOLO_VI_MOTION_FRAME_COUNT(3) | 262 SOLO_VI_MOTION_FRAME_COUNT(3) |
204 SOLO_VI_MOTION_SAMPLE_LENGTH(solo_dev->video_hsize / 16) 263 SOLO_VI_MOTION_SAMPLE_LENGTH(solo_dev->video_hsize / 16)
205 | /* SOLO_VI_MOTION_INTR_START_STOP | */ 264 /* | SOLO_VI_MOTION_INTR_START_STOP */
206 SOLO_VI_MOTION_SAMPLE_COUNT(10)); 265 | SOLO_VI_MOTION_SAMPLE_COUNT(10));
207 266
208 solo_reg_write(solo_dev, SOLO_VI_MOTION_BORDER, 0); 267 solo_reg_write(solo_dev, SOLO_VI_MOTION_BORDER, 0);
209 solo_reg_write(solo_dev, SOLO_VI_MOTION_BAR, 0); 268 solo_reg_write(solo_dev, SOLO_VI_MOTION_BAR, 0);
@@ -226,7 +285,7 @@ int solo_disp_init(struct solo_dev *solo_dev)
226 285
227 solo_vin_config(solo_dev); 286 solo_vin_config(solo_dev);
228 solo_motion_config(solo_dev); 287 solo_motion_config(solo_dev);
229 solo_disp_config(solo_dev); 288 solo_vout_config(solo_dev);
230 289
231 for (i = 0; i < solo_dev->nr_chans; i++) 290 for (i = 0; i < solo_dev->nr_chans; i++)
232 solo_reg_write(solo_dev, SOLO_VI_WIN_ON(i), 1); 291 solo_reg_write(solo_dev, SOLO_VI_WIN_ON(i), 1);
@@ -238,8 +297,6 @@ void solo_disp_exit(struct solo_dev *solo_dev)
238{ 297{
239 int i; 298 int i;
240 299
241 solo_irq_off(solo_dev, SOLO_IRQ_MOTION);
242
243 solo_reg_write(solo_dev, SOLO_VO_DISP_CTRL, 0); 300 solo_reg_write(solo_dev, SOLO_VO_DISP_CTRL, 0);
244 solo_reg_write(solo_dev, SOLO_VO_ZOOM_CTRL, 0); 301 solo_reg_write(solo_dev, SOLO_VO_ZOOM_CTRL, 0);
245 solo_reg_write(solo_dev, SOLO_VO_FREEZE_CTRL, 0); 302 solo_reg_write(solo_dev, SOLO_VO_FREEZE_CTRL, 0);
diff --git a/drivers/staging/media/solo6x10/eeprom.c b/drivers/staging/media/solo6x10/eeprom.c
new file mode 100644
index 000000000000..9d1c9bb53d6b
--- /dev/null
+++ b/drivers/staging/media/solo6x10/eeprom.c
@@ -0,0 +1,154 @@
1/*
2 * Copyright (C) 2010-2013 Bluecherry, LLC <http://www.bluecherrydvr.com>
3 *
4 * Original author:
5 * Ben Collins <bcollins@ubuntu.com>
6 *
7 * Additional work by:
8 * John Brooks <john.brooks@bluecherry.net>
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 as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23 */
24
25#include <linux/kernel.h>
26#include <linux/delay.h>
27
28#include "solo6x10.h"
29
30/* Control */
31#define EE_SHIFT_CLK 0x04
32#define EE_CS 0x08
33#define EE_DATA_WRITE 0x02
34#define EE_DATA_READ 0x01
35#define EE_ENB (0x80 | EE_CS)
36
37#define eeprom_delay() udelay(100)
38#if 0
39#define eeprom_delay() solo_reg_read(solo_dev, SOLO_EEPROM_CTRL)
40#define eeprom_delay() ({ \
41 int i, ret; \
42 udelay(100); \
43 for (i = ret = 0; i < 1000 && !ret; i++) \
44 ret = solo_eeprom_reg_read(solo_dev); \
45})
46#endif
47#define ADDR_LEN 6
48
49/* Commands */
50#define EE_EWEN_CMD 4
51#define EE_EWDS_CMD 4
52#define EE_WRITE_CMD 5
53#define EE_READ_CMD 6
54#define EE_ERASE_CMD 7
55
56static unsigned int solo_eeprom_reg_read(struct solo_dev *solo_dev)
57{
58 return solo_reg_read(solo_dev, SOLO_EEPROM_CTRL) & EE_DATA_READ;
59}
60
61static void solo_eeprom_reg_write(struct solo_dev *solo_dev, u32 data)
62{
63 solo_reg_write(solo_dev, SOLO_EEPROM_CTRL, data);
64 eeprom_delay();
65}
66
67static void solo_eeprom_cmd(struct solo_dev *solo_dev, int cmd)
68{
69 int i;
70
71 solo_eeprom_reg_write(solo_dev, SOLO_EEPROM_ACCESS_EN);
72 solo_eeprom_reg_write(solo_dev, SOLO_EEPROM_ENABLE);
73
74 for (i = 4 + ADDR_LEN; i >= 0; i--) {
75 int dataval = (cmd & (1 << i)) ? EE_DATA_WRITE : 0;
76
77 solo_eeprom_reg_write(solo_dev, SOLO_EEPROM_ENABLE | dataval);
78 solo_eeprom_reg_write(solo_dev, SOLO_EEPROM_ENABLE |
79 EE_SHIFT_CLK | dataval);
80 }
81
82 solo_eeprom_reg_write(solo_dev, SOLO_EEPROM_ENABLE);
83}
84
85unsigned int solo_eeprom_ewen(struct solo_dev *solo_dev, int w_en)
86{
87 int ewen_cmd = (w_en ? 0x3f : 0) | (EE_EWEN_CMD << ADDR_LEN);
88 unsigned int retval = 0;
89 int i;
90
91 solo_eeprom_cmd(solo_dev, ewen_cmd);
92
93 for (i = 0; i < 16; i++) {
94 solo_eeprom_reg_write(solo_dev, SOLO_EEPROM_ENABLE |
95 EE_SHIFT_CLK);
96 retval = (retval << 1) | solo_eeprom_reg_read(solo_dev);
97 solo_eeprom_reg_write(solo_dev, SOLO_EEPROM_ENABLE);
98 retval = (retval << 1) | solo_eeprom_reg_read(solo_dev);
99 }
100
101 solo_eeprom_reg_write(solo_dev, ~EE_CS);
102 retval = (retval << 1) | solo_eeprom_reg_read(solo_dev);
103
104 return retval;
105}
106
107unsigned short solo_eeprom_read(struct solo_dev *solo_dev, int loc)
108{
109 int read_cmd = loc | (EE_READ_CMD << ADDR_LEN);
110 unsigned short retval = 0;
111 int i;
112
113 solo_eeprom_cmd(solo_dev, read_cmd);
114
115 for (i = 0; i < 16; i++) {
116 solo_eeprom_reg_write(solo_dev, SOLO_EEPROM_ENABLE |
117 EE_SHIFT_CLK);
118 retval = (retval << 1) | solo_eeprom_reg_read(solo_dev);
119 solo_eeprom_reg_write(solo_dev, SOLO_EEPROM_ENABLE);
120 }
121
122 solo_eeprom_reg_write(solo_dev, ~EE_CS);
123
124 return retval;
125}
126
127int solo_eeprom_write(struct solo_dev *solo_dev, int loc,
128 unsigned short data)
129{
130 int write_cmd = loc | (EE_WRITE_CMD << ADDR_LEN);
131 unsigned int retval;
132 int i;
133
134 solo_eeprom_cmd(solo_dev, write_cmd);
135
136 for (i = 15; i >= 0; i--) {
137 unsigned int dataval = (data >> i) & 1;
138
139 solo_eeprom_reg_write(solo_dev, EE_ENB);
140 solo_eeprom_reg_write(solo_dev,
141 EE_ENB | (dataval << 1) | EE_SHIFT_CLK);
142 }
143
144 solo_eeprom_reg_write(solo_dev, EE_ENB);
145 solo_eeprom_reg_write(solo_dev, ~EE_CS);
146 solo_eeprom_reg_write(solo_dev, EE_ENB);
147
148 for (i = retval = 0; i < 10000 && !retval; i++)
149 retval = solo_eeprom_reg_read(solo_dev);
150
151 solo_eeprom_reg_write(solo_dev, ~EE_CS);
152
153 return !retval;
154}
diff --git a/drivers/staging/media/solo6x10/enc.c b/drivers/staging/media/solo6x10/enc.c
index de502599bb19..94d5735abf85 100644
--- a/drivers/staging/media/solo6x10/enc.c
+++ b/drivers/staging/media/solo6x10/enc.c
@@ -1,6 +1,11 @@
1/* 1/*
2 * Copyright (C) 2010 Bluecherry, LLC www.bluecherrydvr.com 2 * Copyright (C) 2010-2013 Bluecherry, LLC <http://www.bluecherrydvr.com>
3 * Copyright (C) 2010 Ben Collins <bcollins@bluecherry.net> 3 *
4 * Original author:
5 * Ben Collins <bcollins@ubuntu.com>
6 *
7 * Additional work by:
8 * John Brooks <john.brooks@bluecherry.net>
4 * 9 *
5 * This program is free software; you can redistribute it and/or modify 10 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by 11 * it under the terms of the GNU General Public License as published by
@@ -18,30 +23,41 @@
18 */ 23 */
19 24
20#include <linux/kernel.h> 25#include <linux/kernel.h>
26#include <linux/font.h>
27#include <linux/bitrev.h>
21#include <linux/slab.h> 28#include <linux/slab.h>
22#include "solo6x10.h"
23#include "osd-font.h"
24 29
25#define CAPTURE_MAX_BANDWIDTH 32 /* D1 4channel (D1 == 4) */ 30#include "solo6x10.h"
26#define OSG_BUFFER_SIZE 1024
27 31
28#define VI_PROG_HSIZE (1280 - 16) 32#define VI_PROG_HSIZE (1280 - 16)
29#define VI_PROG_VSIZE (1024 - 16) 33#define VI_PROG_VSIZE (1024 - 16)
30 34
35#define IRQ_LEVEL 2
36
31static void solo_capture_config(struct solo_dev *solo_dev) 37static void solo_capture_config(struct solo_dev *solo_dev)
32{ 38{
33 int i, j;
34 unsigned long height; 39 unsigned long height;
35 unsigned long width; 40 unsigned long width;
36 unsigned char *buf; 41 void *buf;
42 int i;
37 43
38 solo_reg_write(solo_dev, SOLO_CAP_BASE, 44 solo_reg_write(solo_dev, SOLO_CAP_BASE,
39 SOLO_CAP_MAX_PAGE(SOLO_CAP_EXT_MAX_PAGE * 45 SOLO_CAP_MAX_PAGE((SOLO_CAP_EXT_SIZE(solo_dev)
40 solo_dev->nr_chans) | 46 - SOLO_CAP_PAGE_SIZE) >> 16)
41 SOLO_CAP_BASE_ADDR(SOLO_CAP_EXT_ADDR(solo_dev) >> 16)); 47 | SOLO_CAP_BASE_ADDR(SOLO_CAP_EXT_ADDR(solo_dev) >> 16));
42 solo_reg_write(solo_dev, SOLO_CAP_BTW, 48
43 (1 << 17) | SOLO_CAP_PROG_BANDWIDTH(2) | 49 /* XXX: Undocumented bits at b17 and b24 */
44 SOLO_CAP_MAX_BANDWIDTH(CAPTURE_MAX_BANDWIDTH)); 50 if (solo_dev->type == SOLO_DEV_6110) {
51 /* NOTE: Ref driver has (62 << 24) here as well, but it causes
52 * wacked out frame timing on 4-port 6110. */
53 solo_reg_write(solo_dev, SOLO_CAP_BTW,
54 (1 << 17) | SOLO_CAP_PROG_BANDWIDTH(2) |
55 SOLO_CAP_MAX_BANDWIDTH(36));
56 } else {
57 solo_reg_write(solo_dev, SOLO_CAP_BTW,
58 (1 << 17) | SOLO_CAP_PROG_BANDWIDTH(2) |
59 SOLO_CAP_MAX_BANDWIDTH(32));
60 }
45 61
46 /* Set scale 1, 9 dimension */ 62 /* Set scale 1, 9 dimension */
47 width = solo_dev->video_hsize; 63 width = solo_dev->video_hsize;
@@ -96,115 +112,212 @@ static void solo_capture_config(struct solo_dev *solo_dev)
96 solo_reg_write(solo_dev, SOLO_VE_OSD_BASE, SOLO_EOSD_EXT_ADDR >> 16); 112 solo_reg_write(solo_dev, SOLO_VE_OSD_BASE, SOLO_EOSD_EXT_ADDR >> 16);
97 solo_reg_write(solo_dev, SOLO_VE_OSD_CLR, 113 solo_reg_write(solo_dev, SOLO_VE_OSD_CLR,
98 0xF0 << 16 | 0x80 << 8 | 0x80); 114 0xF0 << 16 | 0x80 << 8 | 0x80);
99 solo_reg_write(solo_dev, SOLO_VE_OSD_OPT, 0); 115
116 if (solo_dev->type == SOLO_DEV_6010)
117 solo_reg_write(solo_dev, SOLO_VE_OSD_OPT,
118 SOLO_VE_OSD_H_SHADOW | SOLO_VE_OSD_V_SHADOW);
119 else
120 solo_reg_write(solo_dev, SOLO_VE_OSD_OPT, SOLO_VE_OSD_V_DOUBLE
121 | SOLO_VE_OSD_H_SHADOW | SOLO_VE_OSD_V_SHADOW);
100 122
101 /* Clear OSG buffer */ 123 /* Clear OSG buffer */
102 buf = kzalloc(OSG_BUFFER_SIZE, GFP_KERNEL); 124 buf = kzalloc(SOLO_EOSD_EXT_SIZE(solo_dev), GFP_KERNEL);
103 if (!buf) 125 if (!buf)
104 return; 126 return;
105 127
106 for (i = 0; i < solo_dev->nr_chans; i++) { 128 for (i = 0; i < solo_dev->nr_chans; i++) {
107 for (j = 0; j < SOLO_EOSD_EXT_SIZE; j += OSG_BUFFER_SIZE) { 129 solo_p2m_dma(solo_dev, 1, buf,
108 solo_p2m_dma(solo_dev, SOLO_P2M_DMA_ID_MP4E, 1, buf, 130 SOLO_EOSD_EXT_ADDR +
109 SOLO_EOSD_EXT_ADDR + 131 (SOLO_EOSD_EXT_SIZE(solo_dev) * i),
110 (i * SOLO_EOSD_EXT_SIZE) + j, 132 SOLO_EOSD_EXT_SIZE(solo_dev), 0, 0);
111 OSG_BUFFER_SIZE);
112 }
113 } 133 }
114 kfree(buf); 134 kfree(buf);
115} 135}
116 136
137/* Should be called with enable_lock held */
117int solo_osd_print(struct solo_enc_dev *solo_enc) 138int solo_osd_print(struct solo_enc_dev *solo_enc)
118{ 139{
119 struct solo_dev *solo_dev = solo_enc->solo_dev; 140 struct solo_dev *solo_dev = solo_enc->solo_dev;
120 char *str = solo_enc->osd_text; 141 unsigned char *str = solo_enc->osd_text;
121 u8 *buf; 142 u8 *buf = solo_enc->osd_buf;
122 u32 reg = solo_reg_read(solo_dev, SOLO_VE_OSD_CH); 143 u32 reg = solo_reg_read(solo_dev, SOLO_VE_OSD_CH);
123 int len = strlen(str); 144 const struct font_desc *vga = find_font("VGA8x16");
145 const unsigned char *vga_data;
146 int len;
124 int i, j; 147 int i, j;
125 int x = 1, y = 1; 148
149 if (WARN_ON_ONCE(!vga))
150 return -ENODEV;
151
152 len = strlen(str);
126 153
127 if (len == 0) { 154 if (len == 0) {
155 /* Disable OSD on this channel */
128 reg &= ~(1 << solo_enc->ch); 156 reg &= ~(1 << solo_enc->ch);
129 solo_reg_write(solo_dev, SOLO_VE_OSD_CH, reg); 157 solo_reg_write(solo_dev, SOLO_VE_OSD_CH, reg);
130 return 0; 158 return 0;
131 } 159 }
132 160
133 buf = kzalloc(SOLO_EOSD_EXT_SIZE, GFP_KERNEL); 161 memset(buf, 0, SOLO_EOSD_EXT_SIZE_MAX);
134 if (!buf) 162 vga_data = (const unsigned char *)vga->data;
135 return -ENOMEM;
136 163
137 for (i = 0; i < len; i++) { 164 for (i = 0; i < len; i++) {
165 unsigned char c = str[i];
166
138 for (j = 0; j < 16; j++) { 167 for (j = 0; j < 16; j++) {
139 buf[(j*2) + (i%2) + ((x + (i/2)) * 32) + (y * 2048)] = 168 buf[(j * 2) + (i % 2) + (i / 2 * 32)] =
140 (solo_osd_font[(str[i] * 4) + (j / 4)] 169 bitrev8(vga_data[(c * 16) + j]);
141 >> ((3 - (j % 4)) * 8)) & 0xff;
142 } 170 }
143 } 171 }
144 172
145 solo_p2m_dma(solo_dev, 0, 1, buf, SOLO_EOSD_EXT_ADDR + 173 solo_p2m_dma(solo_dev, 1, buf,
146 (solo_enc->ch * SOLO_EOSD_EXT_SIZE), SOLO_EOSD_EXT_SIZE); 174 SOLO_EOSD_EXT_ADDR +
175 (solo_enc->ch * SOLO_EOSD_EXT_SIZE(solo_dev)),
176 SOLO_EOSD_EXT_SIZE(solo_dev), 0, 0);
177
178 /* Enable OSD on this channel */
147 reg |= (1 << solo_enc->ch); 179 reg |= (1 << solo_enc->ch);
148 solo_reg_write(solo_dev, SOLO_VE_OSD_CH, reg); 180 solo_reg_write(solo_dev, SOLO_VE_OSD_CH, reg);
149 181
150 kfree(buf);
151
152 return 0; 182 return 0;
153} 183}
154 184
185/**
186 * Set channel Quality Profile (0-3).
187 */
188void solo_s_jpeg_qp(struct solo_dev *solo_dev, unsigned int ch,
189 unsigned int qp)
190{
191 unsigned long flags;
192 unsigned int idx, reg;
193
194 if ((ch > 31) || (qp > 3))
195 return;
196
197 if (solo_dev->type == SOLO_DEV_6010)
198 return;
199
200 if (ch < 16) {
201 idx = 0;
202 reg = SOLO_VE_JPEG_QP_CH_L;
203 } else {
204 ch -= 16;
205 idx = 1;
206 reg = SOLO_VE_JPEG_QP_CH_H;
207 }
208 ch *= 2;
209
210 spin_lock_irqsave(&solo_dev->jpeg_qp_lock, flags);
211
212 solo_dev->jpeg_qp[idx] &= ~(3 << ch);
213 solo_dev->jpeg_qp[idx] |= (qp & 3) << ch;
214
215 solo_reg_write(solo_dev, reg, solo_dev->jpeg_qp[idx]);
216
217 spin_unlock_irqrestore(&solo_dev->jpeg_qp_lock, flags);
218}
219
220int solo_g_jpeg_qp(struct solo_dev *solo_dev, unsigned int ch)
221{
222 int idx;
223
224 if (solo_dev->type == SOLO_DEV_6010)
225 return 2;
226
227 if (WARN_ON_ONCE(ch > 31))
228 return 2;
229
230 if (ch < 16) {
231 idx = 0;
232 } else {
233 ch -= 16;
234 idx = 1;
235 }
236 ch *= 2;
237
238 return (solo_dev->jpeg_qp[idx] >> ch) & 3;
239}
240
241#define SOLO_QP_INIT 0xaaaaaaaa
242
155static void solo_jpeg_config(struct solo_dev *solo_dev) 243static void solo_jpeg_config(struct solo_dev *solo_dev)
156{ 244{
157 u32 reg; 245 if (solo_dev->type == SOLO_DEV_6010) {
158 if (solo_dev->flags & FLAGS_6110) 246 solo_reg_write(solo_dev, SOLO_VE_JPEG_QP_TBL,
159 reg = (4 << 24) | (3 << 16) | (2 << 8) | (1 << 0); 247 (2 << 24) | (2 << 16) | (2 << 8) | 2);
160 else 248 } else {
161 reg = (2 << 24) | (2 << 16) | (2 << 8) | (2 << 0); 249 solo_reg_write(solo_dev, SOLO_VE_JPEG_QP_TBL,
162 solo_reg_write(solo_dev, SOLO_VE_JPEG_QP_TBL, reg); 250 (4 << 24) | (3 << 16) | (2 << 8) | 1);
163 solo_reg_write(solo_dev, SOLO_VE_JPEG_QP_CH_L, 0); 251 }
164 solo_reg_write(solo_dev, SOLO_VE_JPEG_QP_CH_H, 0); 252
253 spin_lock_init(&solo_dev->jpeg_qp_lock);
254
255 /* Initialize Quality Profile for all channels */
256 solo_dev->jpeg_qp[0] = solo_dev->jpeg_qp[1] = SOLO_QP_INIT;
257 solo_reg_write(solo_dev, SOLO_VE_JPEG_QP_CH_L, SOLO_QP_INIT);
258 solo_reg_write(solo_dev, SOLO_VE_JPEG_QP_CH_H, SOLO_QP_INIT);
259
165 solo_reg_write(solo_dev, SOLO_VE_JPEG_CFG, 260 solo_reg_write(solo_dev, SOLO_VE_JPEG_CFG,
166 (SOLO_JPEG_EXT_SIZE(solo_dev) & 0xffff0000) | 261 (SOLO_JPEG_EXT_SIZE(solo_dev) & 0xffff0000) |
167 ((SOLO_JPEG_EXT_ADDR(solo_dev) >> 16) & 0x0000ffff)); 262 ((SOLO_JPEG_EXT_ADDR(solo_dev) >> 16) & 0x0000ffff));
168 solo_reg_write(solo_dev, SOLO_VE_JPEG_CTRL, 0xffffffff); 263 solo_reg_write(solo_dev, SOLO_VE_JPEG_CTRL, 0xffffffff);
169 /* que limit, samp limit, pos limit */ 264 if (solo_dev->type == SOLO_DEV_6110) {
170 solo_reg_write(solo_dev, 0x0688, (0 << 16) | (30 << 8) | 60); 265 solo_reg_write(solo_dev, SOLO_VE_JPEG_CFG1,
266 (0 << 16) | (30 << 8) | 60);
267 }
171} 268}
172 269
173static void solo_mp4e_config(struct solo_dev *solo_dev) 270static void solo_mp4e_config(struct solo_dev *solo_dev)
174{ 271{
175 int i; 272 int i;
176 u32 reg; 273 u32 cfg;
177 274
178 /* We can only use VE_INTR_CTRL(0) if we want to support mjpeg */
179 solo_reg_write(solo_dev, SOLO_VE_CFG0, 275 solo_reg_write(solo_dev, SOLO_VE_CFG0,
180 SOLO_VE_INTR_CTRL(0) | 276 SOLO_VE_INTR_CTRL(IRQ_LEVEL) |
181 SOLO_VE_BLOCK_SIZE(SOLO_MP4E_EXT_SIZE(solo_dev) >> 16) | 277 SOLO_VE_BLOCK_SIZE(SOLO_MP4E_EXT_SIZE(solo_dev) >> 16) |
182 SOLO_VE_BLOCK_BASE(SOLO_MP4E_EXT_ADDR(solo_dev) >> 16)); 278 SOLO_VE_BLOCK_BASE(SOLO_MP4E_EXT_ADDR(solo_dev) >> 16));
183 279
184 solo_reg_write(solo_dev, SOLO_VE_CFG1, 280
185 SOLO_VE_INSERT_INDEX | SOLO_VE_MOTION_MODE(0)); 281 cfg = SOLO_VE_BYTE_ALIGN(2) | SOLO_VE_INSERT_INDEX
282 | SOLO_VE_MOTION_MODE(0);
283 if (solo_dev->type != SOLO_DEV_6010) {
284 cfg |= SOLO_VE_MPEG_SIZE_H(
285 (SOLO_MP4E_EXT_SIZE(solo_dev) >> 24) & 0x0f);
286 cfg |= SOLO_VE_JPEG_SIZE_H(
287 (SOLO_JPEG_EXT_SIZE(solo_dev) >> 24) & 0x0f);
288 }
289 solo_reg_write(solo_dev, SOLO_VE_CFG1, cfg);
186 290
187 solo_reg_write(solo_dev, SOLO_VE_WMRK_POLY, 0); 291 solo_reg_write(solo_dev, SOLO_VE_WMRK_POLY, 0);
188 solo_reg_write(solo_dev, SOLO_VE_VMRK_INIT_KEY, 0); 292 solo_reg_write(solo_dev, SOLO_VE_VMRK_INIT_KEY, 0);
189 solo_reg_write(solo_dev, SOLO_VE_WMRK_STRL, 0); 293 solo_reg_write(solo_dev, SOLO_VE_WMRK_STRL, 0);
294 if (solo_dev->type == SOLO_DEV_6110)
295 solo_reg_write(solo_dev, SOLO_VE_WMRK_ENABLE, 0);
190 solo_reg_write(solo_dev, SOLO_VE_ENCRYP_POLY, 0); 296 solo_reg_write(solo_dev, SOLO_VE_ENCRYP_POLY, 0);
191 solo_reg_write(solo_dev, SOLO_VE_ENCRYP_INIT, 0); 297 solo_reg_write(solo_dev, SOLO_VE_ENCRYP_INIT, 0);
192 298
193 reg = SOLO_VE_LITTLE_ENDIAN | SOLO_COMP_ATTR_FCODE(1) | 299 solo_reg_write(solo_dev, SOLO_VE_ATTR,
194 SOLO_COMP_TIME_INC(0) | SOLO_COMP_TIME_WIDTH(15); 300 SOLO_VE_LITTLE_ENDIAN |
195 if (solo_dev->flags & FLAGS_6110) 301 SOLO_COMP_ATTR_FCODE(1) |
196 reg |= SOLO_DCT_INTERVAL(10); 302 SOLO_COMP_TIME_INC(0) |
197 else 303 SOLO_COMP_TIME_WIDTH(15) |
198 reg |= SOLO_DCT_INTERVAL(36 / 4); 304 SOLO_DCT_INTERVAL(solo_dev->type == SOLO_DEV_6010 ? 9 : 10));
199 solo_reg_write(solo_dev, SOLO_VE_ATTR, reg);
200 305
201 for (i = 0; i < solo_dev->nr_chans; i++) 306 for (i = 0; i < solo_dev->nr_chans; i++) {
202 solo_reg_write(solo_dev, SOLO_VE_CH_REF_BASE(i), 307 solo_reg_write(solo_dev, SOLO_VE_CH_REF_BASE(i),
203 (SOLO_EREF_EXT_ADDR(solo_dev) + 308 (SOLO_EREF_EXT_ADDR(solo_dev) +
204 (i * SOLO_EREF_EXT_SIZE)) >> 16); 309 (i * SOLO_EREF_EXT_SIZE)) >> 16);
310 solo_reg_write(solo_dev, SOLO_VE_CH_REF_BASE_E(i),
311 (SOLO_EREF_EXT_ADDR(solo_dev) +
312 ((i + 16) * SOLO_EREF_EXT_SIZE)) >> 16);
313 }
205 314
206 if (solo_dev->flags & FLAGS_6110) 315 if (solo_dev->type == SOLO_DEV_6110) {
207 solo_reg_write(solo_dev, 0x0634, 0x00040008); /* ? */ 316 solo_reg_write(solo_dev, SOLO_VE_COMPT_MOT, 0x00040008);
317 } else {
318 for (i = 0; i < solo_dev->nr_chans; i++)
319 solo_reg_write(solo_dev, SOLO_VE_CH_MOT(i), 0x100);
320 }
208} 321}
209 322
210int solo_enc_init(struct solo_dev *solo_dev) 323int solo_enc_init(struct solo_dev *solo_dev)
@@ -220,8 +333,6 @@ int solo_enc_init(struct solo_dev *solo_dev)
220 solo_reg_write(solo_dev, SOLO_CAP_CH_COMP_ENA_E(i), 0); 333 solo_reg_write(solo_dev, SOLO_CAP_CH_COMP_ENA_E(i), 0);
221 } 334 }
222 335
223 solo_irq_on(solo_dev, SOLO_IRQ_ENCODER);
224
225 return 0; 336 return 0;
226} 337}
227 338
@@ -229,8 +340,6 @@ void solo_enc_exit(struct solo_dev *solo_dev)
229{ 340{
230 int i; 341 int i;
231 342
232 solo_irq_off(solo_dev, SOLO_IRQ_ENCODER);
233
234 for (i = 0; i < solo_dev->nr_chans; i++) { 343 for (i = 0; i < solo_dev->nr_chans; i++) {
235 solo_reg_write(solo_dev, SOLO_CAP_CH_SCALE(i), 0); 344 solo_reg_write(solo_dev, SOLO_CAP_CH_SCALE(i), 0);
236 solo_reg_write(solo_dev, SOLO_CAP_CH_COMP_ENA_E(i), 0); 345 solo_reg_write(solo_dev, SOLO_CAP_CH_COMP_ENA_E(i), 0);
diff --git a/drivers/staging/media/solo6x10/g723.c b/drivers/staging/media/solo6x10/g723.c
index 2cd0de28a633..183222e7ee95 100644
--- a/drivers/staging/media/solo6x10/g723.c
+++ b/drivers/staging/media/solo6x10/g723.c
@@ -1,6 +1,11 @@
1/* 1/*
2 * Copyright (C) 2010 Bluecherry, LLC www.bluecherrydvr.com 2 * Copyright (C) 2010-2013 Bluecherry, LLC <http://www.bluecherrydvr.com>
3 * Copyright (C) 2010 Ben Collins <bcollins@bluecherry.net> 3 *
4 * Original author:
5 * Ben Collins <bcollins@ubuntu.com>
6 *
7 * Additional work by:
8 * John Brooks <john.brooks@bluecherry.net>
4 * 9 *
5 * This program is free software; you can redistribute it and/or modify 10 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by 11 * it under the terms of the GNU General Public License as published by
@@ -21,17 +26,18 @@
21#include <linux/mempool.h> 26#include <linux/mempool.h>
22#include <linux/poll.h> 27#include <linux/poll.h>
23#include <linux/kthread.h> 28#include <linux/kthread.h>
24#include <linux/slab.h>
25#include <linux/freezer.h> 29#include <linux/freezer.h>
26#include <linux/export.h> 30#include <linux/module.h>
31#include <linux/slab.h>
32
27#include <sound/core.h> 33#include <sound/core.h>
28#include <sound/initval.h> 34#include <sound/initval.h>
29#include <sound/pcm.h> 35#include <sound/pcm.h>
30#include <sound/control.h> 36#include <sound/control.h>
37
31#include "solo6x10.h" 38#include "solo6x10.h"
32#include "tw28.h" 39#include "tw28.h"
33 40
34#define G723_INTR_ORDER 0
35#define G723_FDMA_PAGES 32 41#define G723_FDMA_PAGES 32
36#define G723_PERIOD_BYTES 48 42#define G723_PERIOD_BYTES 48
37#define G723_PERIOD_BLOCK 1024 43#define G723_PERIOD_BLOCK 1024
@@ -46,36 +52,40 @@
46/* The solo writes to 1k byte pages, 32 pages, in the dma. Each 1k page 52/* The solo writes to 1k byte pages, 32 pages, in the dma. Each 1k page
47 * is broken down to 20 * 48 byte regions (one for each channel possible) 53 * is broken down to 20 * 48 byte regions (one for each channel possible)
48 * with the rest of the page being dummy data. */ 54 * with the rest of the page being dummy data. */
49#define MAX_BUFFER (G723_PERIOD_BYTES * PERIODS_MAX) 55#define G723_MAX_BUFFER (G723_PERIOD_BYTES * PERIODS_MAX)
50#define IRQ_PAGES 4 /* 0 - 4 */ 56#define G723_INTR_ORDER 4 /* 0 - 4 */
51#define PERIODS_MIN (1 << IRQ_PAGES) 57#define PERIODS_MIN (1 << G723_INTR_ORDER)
52#define PERIODS_MAX G723_FDMA_PAGES 58#define PERIODS_MAX G723_FDMA_PAGES
53 59
54struct solo_snd_pcm { 60struct solo_snd_pcm {
55 int on; 61 int on;
56 spinlock_t lock; 62 spinlock_t lock;
57 struct solo_dev *solo_dev; 63 struct solo_dev *solo_dev;
58 unsigned char g723_buf[G723_PERIOD_BYTES]; 64 unsigned char *g723_buf;
65 dma_addr_t g723_dma;
59}; 66};
60 67
61static void solo_g723_config(struct solo_dev *solo_dev) 68static void solo_g723_config(struct solo_dev *solo_dev)
62{ 69{
63 int clk_div; 70 int clk_div;
64 71
65 clk_div = SOLO_CLOCK_MHZ / (SAMPLERATE * (BITRATE * 2) * 2); 72 clk_div = (solo_dev->clock_mhz * 1000000)
73 / (SAMPLERATE * (BITRATE * 2) * 2);
66 74
67 solo_reg_write(solo_dev, SOLO_AUDIO_SAMPLE, 75 solo_reg_write(solo_dev, SOLO_AUDIO_SAMPLE,
68 SOLO_AUDIO_BITRATE(BITRATE) | 76 SOLO_AUDIO_BITRATE(BITRATE)
69 SOLO_AUDIO_CLK_DIV(clk_div)); 77 | SOLO_AUDIO_CLK_DIV(clk_div));
70 78
71 solo_reg_write(solo_dev, SOLO_AUDIO_FDMA_INTR, 79 solo_reg_write(solo_dev, SOLO_AUDIO_FDMA_INTR,
72 SOLO_AUDIO_FDMA_INTERVAL(IRQ_PAGES) | 80 SOLO_AUDIO_FDMA_INTERVAL(1)
73 SOLO_AUDIO_INTR_ORDER(G723_INTR_ORDER) | 81 | SOLO_AUDIO_INTR_ORDER(G723_INTR_ORDER)
74 SOLO_AUDIO_FDMA_BASE(SOLO_G723_EXT_ADDR(solo_dev) >> 16)); 82 | SOLO_AUDIO_FDMA_BASE(SOLO_G723_EXT_ADDR(solo_dev) >> 16));
75 83
76 solo_reg_write(solo_dev, SOLO_AUDIO_CONTROL, 84 solo_reg_write(solo_dev, SOLO_AUDIO_CONTROL,
77 SOLO_AUDIO_ENABLE | SOLO_AUDIO_I2S_MODE | 85 SOLO_AUDIO_ENABLE
78 SOLO_AUDIO_I2S_MULTI(3) | SOLO_AUDIO_MODE(OUTMODE_MASK)); 86 | SOLO_AUDIO_I2S_MODE
87 | SOLO_AUDIO_I2S_MULTI(3)
88 | SOLO_AUDIO_MODE(OUTMODE_MASK));
79} 89}
80 90
81void solo_g723_isr(struct solo_dev *solo_dev) 91void solo_g723_isr(struct solo_dev *solo_dev)
@@ -85,8 +95,6 @@ void solo_g723_isr(struct solo_dev *solo_dev)
85 struct snd_pcm_substream *ss; 95 struct snd_pcm_substream *ss;
86 struct solo_snd_pcm *solo_pcm; 96 struct solo_snd_pcm *solo_pcm;
87 97
88 solo_reg_write(solo_dev, SOLO_IRQ_STAT, SOLO_IRQ_G723);
89
90 for (ss = pstr->substream; ss != NULL; ss = ss->next) { 98 for (ss = pstr->substream; ss != NULL; ss = ss->next) {
91 if (snd_pcm_substream_chip(ss) == NULL) 99 if (snd_pcm_substream_chip(ss) == NULL)
92 continue; 100 continue;
@@ -115,18 +123,18 @@ static int snd_solo_hw_free(struct snd_pcm_substream *ss)
115 return snd_pcm_lib_free_pages(ss); 123 return snd_pcm_lib_free_pages(ss);
116} 124}
117 125
118static struct snd_pcm_hardware snd_solo_pcm_hw = { 126static const struct snd_pcm_hardware snd_solo_pcm_hw = {
119 .info = (SNDRV_PCM_INFO_MMAP | 127 .info = (SNDRV_PCM_INFO_MMAP |
120 SNDRV_PCM_INFO_INTERLEAVED | 128 SNDRV_PCM_INFO_INTERLEAVED |
121 SNDRV_PCM_INFO_BLOCK_TRANSFER | 129 SNDRV_PCM_INFO_BLOCK_TRANSFER |
122 SNDRV_PCM_INFO_MMAP_VALID), 130 SNDRV_PCM_INFO_MMAP_VALID),
123 .formats = SNDRV_PCM_FMTBIT_U8, 131 .formats = SNDRV_PCM_FMTBIT_U8,
124 .rates = SNDRV_PCM_RATE_8000, 132 .rates = SNDRV_PCM_RATE_8000,
125 .rate_min = 8000, 133 .rate_min = SAMPLERATE,
126 .rate_max = 8000, 134 .rate_max = SAMPLERATE,
127 .channels_min = 1, 135 .channels_min = 1,
128 .channels_max = 1, 136 .channels_max = 1,
129 .buffer_bytes_max = MAX_BUFFER, 137 .buffer_bytes_max = G723_MAX_BUFFER,
130 .period_bytes_min = G723_PERIOD_BYTES, 138 .period_bytes_min = G723_PERIOD_BYTES,
131 .period_bytes_max = G723_PERIOD_BYTES, 139 .period_bytes_max = G723_PERIOD_BYTES,
132 .periods_min = PERIODS_MIN, 140 .periods_min = PERIODS_MIN,
@@ -140,7 +148,13 @@ static int snd_solo_pcm_open(struct snd_pcm_substream *ss)
140 148
141 solo_pcm = kzalloc(sizeof(*solo_pcm), GFP_KERNEL); 149 solo_pcm = kzalloc(sizeof(*solo_pcm), GFP_KERNEL);
142 if (solo_pcm == NULL) 150 if (solo_pcm == NULL)
143 return -ENOMEM; 151 goto oom;
152
153 solo_pcm->g723_buf = pci_alloc_consistent(solo_dev->pdev,
154 G723_PERIOD_BYTES,
155 &solo_pcm->g723_dma);
156 if (solo_pcm->g723_buf == NULL)
157 goto oom;
144 158
145 spin_lock_init(&solo_pcm->lock); 159 spin_lock_init(&solo_pcm->lock);
146 solo_pcm->solo_dev = solo_dev; 160 solo_pcm->solo_dev = solo_dev;
@@ -149,6 +163,10 @@ static int snd_solo_pcm_open(struct snd_pcm_substream *ss)
149 snd_pcm_substream_chip(ss) = solo_pcm; 163 snd_pcm_substream_chip(ss) = solo_pcm;
150 164
151 return 0; 165 return 0;
166
167oom:
168 kfree(solo_pcm);
169 return -ENOMEM;
152} 170}
153 171
154static int snd_solo_pcm_close(struct snd_pcm_substream *ss) 172static int snd_solo_pcm_close(struct snd_pcm_substream *ss)
@@ -156,6 +174,8 @@ static int snd_solo_pcm_close(struct snd_pcm_substream *ss)
156 struct solo_snd_pcm *solo_pcm = snd_pcm_substream_chip(ss); 174 struct solo_snd_pcm *solo_pcm = snd_pcm_substream_chip(ss);
157 175
158 snd_pcm_substream_chip(ss) = solo_pcm->solo_dev; 176 snd_pcm_substream_chip(ss) = solo_pcm->solo_dev;
177 pci_free_consistent(solo_pcm->solo_dev->pdev, G723_PERIOD_BYTES,
178 solo_pcm->g723_buf, solo_pcm->g723_dma);
159 kfree(solo_pcm); 179 kfree(solo_pcm);
160 180
161 return 0; 181 return 0;
@@ -220,12 +240,11 @@ static int snd_solo_pcm_copy(struct snd_pcm_substream *ss, int channel,
220 for (i = 0; i < (count / G723_FRAMES_PER_PAGE); i++) { 240 for (i = 0; i < (count / G723_FRAMES_PER_PAGE); i++) {
221 int page = (pos / G723_FRAMES_PER_PAGE) + i; 241 int page = (pos / G723_FRAMES_PER_PAGE) + i;
222 242
223 err = solo_p2m_dma(solo_dev, SOLO_P2M_DMA_ID_G723E, 0, 243 err = solo_p2m_dma_t(solo_dev, 0, solo_pcm->g723_dma,
224 solo_pcm->g723_buf, 244 SOLO_G723_EXT_ADDR(solo_dev) +
225 SOLO_G723_EXT_ADDR(solo_dev) + 245 (page * G723_PERIOD_BLOCK) +
226 (page * G723_PERIOD_BLOCK) + 246 (ss->number * G723_PERIOD_BYTES),
227 (ss->number * G723_PERIOD_BYTES), 247 G723_PERIOD_BYTES, 0, 0);
228 G723_PERIOD_BYTES);
229 if (err) 248 if (err)
230 return err; 249 return err;
231 250
@@ -325,7 +344,7 @@ static int solo_snd_pcm_init(struct solo_dev *solo_dev)
325 ret = snd_pcm_lib_preallocate_pages_for_all(pcm, 344 ret = snd_pcm_lib_preallocate_pages_for_all(pcm,
326 SNDRV_DMA_TYPE_CONTINUOUS, 345 SNDRV_DMA_TYPE_CONTINUOUS,
327 snd_dma_continuous_data(GFP_KERNEL), 346 snd_dma_continuous_data(GFP_KERNEL),
328 MAX_BUFFER, MAX_BUFFER); 347 G723_MAX_BUFFER, G723_MAX_BUFFER);
329 if (ret < 0) 348 if (ret < 0)
330 return ret; 349 return ret;
331 350
@@ -368,6 +387,7 @@ int solo_g723_init(struct solo_dev *solo_dev)
368 strcpy(card->mixername, "SOLO-6x10"); 387 strcpy(card->mixername, "SOLO-6x10");
369 kctl = snd_solo_capture_volume; 388 kctl = snd_solo_capture_volume;
370 kctl.count = solo_dev->nr_chans; 389 kctl.count = solo_dev->nr_chans;
390
371 ret = snd_ctl_add(card, snd_ctl_new1(&kctl, solo_dev)); 391 ret = snd_ctl_add(card, snd_ctl_new1(&kctl, solo_dev));
372 if (ret < 0) 392 if (ret < 0)
373 return ret; 393 return ret;
@@ -393,8 +413,12 @@ snd_error:
393 413
394void solo_g723_exit(struct solo_dev *solo_dev) 414void solo_g723_exit(struct solo_dev *solo_dev)
395{ 415{
416 if (!solo_dev->snd_card)
417 return;
418
396 solo_reg_write(solo_dev, SOLO_AUDIO_CONTROL, 0); 419 solo_reg_write(solo_dev, SOLO_AUDIO_CONTROL, 0);
397 solo_irq_off(solo_dev, SOLO_IRQ_G723); 420 solo_irq_off(solo_dev, SOLO_IRQ_G723);
398 421
399 snd_card_free(solo_dev->snd_card); 422 snd_card_free(solo_dev->snd_card);
423 solo_dev->snd_card = NULL;
400} 424}
diff --git a/drivers/staging/media/solo6x10/gpio.c b/drivers/staging/media/solo6x10/gpio.c
index 0925e6f33a99..73276dc92875 100644
--- a/drivers/staging/media/solo6x10/gpio.c
+++ b/drivers/staging/media/solo6x10/gpio.c
@@ -1,6 +1,11 @@
1/* 1/*
2 * Copyright (C) 2010 Bluecherry, LLC www.bluecherrydvr.com 2 * Copyright (C) 2010-2013 Bluecherry, LLC <http://www.bluecherrydvr.com>
3 * Copyright (C) 2010 Ben Collins <bcollins@bluecherry.net> 3 *
4 * Original author:
5 * Ben Collins <bcollins@ubuntu.com>
6 *
7 * Additional work by:
8 * John Brooks <john.brooks@bluecherry.net>
4 * 9 *
5 * This program is free software; you can redistribute it and/or modify 10 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by 11 * it under the terms of the GNU General Public License as published by
@@ -19,7 +24,9 @@
19 24
20#include <linux/kernel.h> 25#include <linux/kernel.h>
21#include <linux/fs.h> 26#include <linux/fs.h>
22#include <asm/uaccess.h> 27#include <linux/delay.h>
28#include <linux/uaccess.h>
29
23#include "solo6x10.h" 30#include "solo6x10.h"
24 31
25static void solo_gpio_mode(struct solo_dev *solo_dev, 32static void solo_gpio_mode(struct solo_dev *solo_dev,
diff --git a/drivers/staging/media/solo6x10/i2c.c b/drivers/staging/media/solo6x10/i2c.c
index 398070a3d293..01aa417c9258 100644
--- a/drivers/staging/media/solo6x10/i2c.c
+++ b/drivers/staging/media/solo6x10/i2c.c
@@ -1,6 +1,11 @@
1/* 1/*
2 * Copyright (C) 2010 Bluecherry, LLC www.bluecherrydvr.com 2 * Copyright (C) 2010-2013 Bluecherry, LLC <http://www.bluecherrydvr.com>
3 * Copyright (C) 2010 Ben Collins <bcollins@bluecherry.net> 3 *
4 * Original author:
5 * Ben Collins <bcollins@ubuntu.com>
6 *
7 * Additional work by:
8 * John Brooks <john.brooks@bluecherry.net>
4 * 9 *
5 * This program is free software; you can redistribute it and/or modify 10 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by 11 * it under the terms of the GNU General Public License as published by
@@ -26,6 +31,7 @@
26 * thread context, ACK the interrupt, and move on. -- BenC */ 31 * thread context, ACK the interrupt, and move on. -- BenC */
27 32
28#include <linux/kernel.h> 33#include <linux/kernel.h>
34
29#include "solo6x10.h" 35#include "solo6x10.h"
30 36
31u8 solo_i2c_readbyte(struct solo_dev *solo_dev, int id, u8 addr, u8 off) 37u8 solo_i2c_readbyte(struct solo_dev *solo_dev, int id, u8 addr, u8 off)
@@ -173,10 +179,9 @@ int solo_i2c_isr(struct solo_dev *solo_dev)
173 u32 status = solo_reg_read(solo_dev, SOLO_IIC_CTRL); 179 u32 status = solo_reg_read(solo_dev, SOLO_IIC_CTRL);
174 int ret = -EINVAL; 180 int ret = -EINVAL;
175 181
176 solo_reg_write(solo_dev, SOLO_IRQ_STAT, SOLO_IRQ_IIC);
177 182
178 if (status & (SOLO_IIC_STATE_TRNS | SOLO_IIC_STATE_SIG_ERR) || 183 if (CHK_FLAGS(status, SOLO_IIC_STATE_TRNS | SOLO_IIC_STATE_SIG_ERR)
179 solo_dev->i2c_id < 0) { 184 || solo_dev->i2c_id < 0) {
180 solo_i2c_stop(solo_dev); 185 solo_i2c_stop(solo_dev);
181 return -ENXIO; 186 return -ENXIO;
182 } 187 }
@@ -239,7 +244,8 @@ static int solo_i2c_master_xfer(struct i2c_adapter *adap,
239 timeout = HZ / 2; 244 timeout = HZ / 2;
240 245
241 for (;;) { 246 for (;;) {
242 prepare_to_wait(&solo_dev->i2c_wait, &wait, TASK_INTERRUPTIBLE); 247 prepare_to_wait(&solo_dev->i2c_wait, &wait,
248 TASK_INTERRUPTIBLE);
243 249
244 if (solo_dev->i2c_state == IIC_STATE_STOP) 250 if (solo_dev->i2c_state == IIC_STATE_STOP)
245 break; 251 break;
@@ -267,7 +273,7 @@ static u32 solo_i2c_functionality(struct i2c_adapter *adap)
267 return I2C_FUNC_I2C; 273 return I2C_FUNC_I2C;
268} 274}
269 275
270static struct i2c_algorithm solo_i2c_algo = { 276static const struct i2c_algorithm solo_i2c_algo = {
271 .master_xfer = solo_i2c_master_xfer, 277 .master_xfer = solo_i2c_master_xfer,
272 .functionality = solo_i2c_functionality, 278 .functionality = solo_i2c_functionality,
273}; 279};
@@ -288,7 +294,8 @@ int solo_i2c_init(struct solo_dev *solo_dev)
288 for (i = 0; i < SOLO_I2C_ADAPTERS; i++) { 294 for (i = 0; i < SOLO_I2C_ADAPTERS; i++) {
289 struct i2c_adapter *adap = &solo_dev->i2c_adap[i]; 295 struct i2c_adapter *adap = &solo_dev->i2c_adap[i];
290 296
291 snprintf(adap->name, I2C_NAME_SIZE, "%s I2C %d", SOLO6X10_NAME, i); 297 snprintf(adap->name, I2C_NAME_SIZE, "%s I2C %d",
298 SOLO6X10_NAME, i);
292 adap->algo = &solo_i2c_algo; 299 adap->algo = &solo_i2c_algo;
293 adap->algo_data = solo_dev; 300 adap->algo_data = solo_dev;
294 adap->retries = 1; 301 adap->retries = 1;
@@ -311,9 +318,6 @@ int solo_i2c_init(struct solo_dev *solo_dev)
311 return ret; 318 return ret;
312 } 319 }
313 320
314 dev_info(&solo_dev->pdev->dev, "Enabled %d i2c adapters\n",
315 SOLO_I2C_ADAPTERS);
316
317 return 0; 321 return 0;
318} 322}
319 323
diff --git a/drivers/staging/media/solo6x10/offsets.h b/drivers/staging/media/solo6x10/offsets.h
index 3d7e569f1cf8..f005dca501f1 100644
--- a/drivers/staging/media/solo6x10/offsets.h
+++ b/drivers/staging/media/solo6x10/offsets.h
@@ -1,6 +1,11 @@
1/* 1/*
2 * Copyright (C) 2010 Bluecherry, LLC www.bluecherrydvr.com 2 * Copyright (C) 2010-2013 Bluecherry, LLC <http://www.bluecherrydvr.com>
3 * Copyright (C) 2010 Ben Collins <bcollins@bluecherry.net> 3 *
4 * Original author:
5 * Ben Collins <bcollins@ubuntu.com>
6 *
7 * Additional work by:
8 * John Brooks <john.brooks@bluecherry.net>
4 * 9 *
5 * This program is free software; you can redistribute it and/or modify 10 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by 11 * it under the terms of the GNU General Public License as published by
@@ -20,55 +25,61 @@
20#ifndef __SOLO6X10_OFFSETS_H 25#ifndef __SOLO6X10_OFFSETS_H
21#define __SOLO6X10_OFFSETS_H 26#define __SOLO6X10_OFFSETS_H
22 27
23/* Offsets and sizes of the external address */
24#define SOLO_DISP_EXT_ADDR 0x00000000 28#define SOLO_DISP_EXT_ADDR 0x00000000
25#define SOLO_DISP_EXT_SIZE 0x00480000 29#define SOLO_DISP_EXT_SIZE 0x00480000
26 30
27#define SOLO_DEC2LIVE_EXT_ADDR (SOLO_DISP_EXT_ADDR + SOLO_DISP_EXT_SIZE) 31#define SOLO_EOSD_EXT_ADDR \
28#define SOLO_DEC2LIVE_EXT_SIZE 0x00240000 32 (SOLO_DISP_EXT_ADDR + SOLO_DISP_EXT_SIZE)
29 33#define SOLO_EOSD_EXT_SIZE(__solo) \
30#define SOLO_OSG_EXT_ADDR (SOLO_DEC2LIVE_EXT_ADDR + SOLO_DEC2LIVE_EXT_SIZE) 34 (__solo->type == SOLO_DEV_6010 ? 0x10000 : 0x20000)
31#define SOLO_OSG_EXT_SIZE 0x00120000 35#define SOLO_EOSD_EXT_SIZE_MAX 0x20000
36#define SOLO_EOSD_EXT_AREA(__solo) \
37 (SOLO_EOSD_EXT_SIZE(__solo) * 32)
32 38
33#define SOLO_EOSD_EXT_ADDR (SOLO_OSG_EXT_ADDR + SOLO_OSG_EXT_SIZE) 39#define SOLO_MOTION_EXT_ADDR(__solo) \
34#define SOLO_EOSD_EXT_SIZE 0x00010000 40 (SOLO_EOSD_EXT_ADDR + SOLO_EOSD_EXT_AREA(__solo))
35
36#define SOLO_MOTION_EXT_ADDR(__solo) (SOLO_EOSD_EXT_ADDR + \
37 (SOLO_EOSD_EXT_SIZE * __solo->nr_chans))
38#define SOLO_MOTION_EXT_SIZE 0x00080000 41#define SOLO_MOTION_EXT_SIZE 0x00080000
39 42
40#define SOLO_G723_EXT_ADDR(__solo) \ 43#define SOLO_G723_EXT_ADDR(__solo) \
41 (SOLO_MOTION_EXT_ADDR(__solo) + SOLO_MOTION_EXT_SIZE) 44 (SOLO_MOTION_EXT_ADDR(__solo) + SOLO_MOTION_EXT_SIZE)
42#define SOLO_G723_EXT_SIZE 0x00010000 45#define SOLO_G723_EXT_SIZE 0x00010000
43 46
44#define SOLO_CAP_EXT_ADDR(__solo) \ 47#define SOLO_CAP_EXT_ADDR(__solo) \
45 (SOLO_G723_EXT_ADDR(__solo) + SOLO_G723_EXT_SIZE) 48 (SOLO_G723_EXT_ADDR(__solo) + SOLO_G723_EXT_SIZE)
46#define SOLO_CAP_EXT_MAX_PAGE (18 + 15) 49
47#define SOLO_CAP_EXT_SIZE (SOLO_CAP_EXT_MAX_PAGE * 65536) 50/* 18 is the maximum number of pages required for PAL@D1, the largest frame
51 * possible */
52#define SOLO_CAP_PAGE_SIZE (18 << 16)
53
54/* Always allow the encoder enough for 16 channels, even if we have less. The
55 * exception is if we have card with only 32Megs of memory. */
56#define SOLO_CAP_EXT_SIZE(__solo) \
57 ((((__solo->sdram_size <= (32 << 20)) ? 4 : 16) + 1) \
58 * SOLO_CAP_PAGE_SIZE)
48 59
49/* This +1 is very important -- Why?! -- BenC */
50#define SOLO_EREF_EXT_ADDR(__solo) \ 60#define SOLO_EREF_EXT_ADDR(__solo) \
51 (SOLO_CAP_EXT_ADDR(__solo) + \ 61 (SOLO_CAP_EXT_ADDR(__solo) + SOLO_CAP_EXT_SIZE(__solo))
52 (SOLO_CAP_EXT_SIZE * (__solo->nr_chans + 1)))
53#define SOLO_EREF_EXT_SIZE 0x00140000 62#define SOLO_EREF_EXT_SIZE 0x00140000
63#define SOLO_EREF_EXT_AREA(__solo) \
64 (SOLO_EREF_EXT_SIZE * __solo->nr_chans * 2)
65
66#define __SOLO_JPEG_MIN_SIZE(__solo) (__solo->nr_chans * 0x00080000)
54 67
55#define SOLO_MP4E_EXT_ADDR(__solo) \ 68#define SOLO_MP4E_EXT_ADDR(__solo) \
56 (SOLO_EREF_EXT_ADDR(__solo) + \ 69 (SOLO_EREF_EXT_ADDR(__solo) + SOLO_EREF_EXT_AREA(__solo))
57 (SOLO_EREF_EXT_SIZE * __solo->nr_chans)) 70#define SOLO_MP4E_EXT_SIZE(__solo) \
58#define SOLO_MP4E_EXT_SIZE(__solo) (0x00080000 * __solo->nr_chans) 71 max((__solo->nr_chans * 0x00080000), \
72 min(((__solo->sdram_size - SOLO_MP4E_EXT_ADDR(__solo)) - \
73 __SOLO_JPEG_MIN_SIZE(__solo)), 0x00ff0000))
59 74
60#define SOLO_DREF_EXT_ADDR(__solo) \ 75#define __SOLO_JPEG_MIN_SIZE(__solo) (__solo->nr_chans * 0x00080000)
76#define SOLO_JPEG_EXT_ADDR(__solo) \
61 (SOLO_MP4E_EXT_ADDR(__solo) + SOLO_MP4E_EXT_SIZE(__solo)) 77 (SOLO_MP4E_EXT_ADDR(__solo) + SOLO_MP4E_EXT_SIZE(__solo))
62#define SOLO_DREF_EXT_SIZE 0x00140000 78#define SOLO_JPEG_EXT_SIZE(__solo) \
79 max(__SOLO_JPEG_MIN_SIZE(__solo), \
80 min((__solo->sdram_size - SOLO_JPEG_EXT_ADDR(__solo)), 0x00ff0000))
63 81
64#define SOLO_MP4D_EXT_ADDR(__solo) \ 82#define SOLO_SDRAM_END(__solo) \
65 (SOLO_DREF_EXT_ADDR(__solo) + \ 83 (SOLO_JPEG_EXT_ADDR(__solo) + SOLO_JPEG_EXT_SIZE(__solo))
66 (SOLO_DREF_EXT_SIZE * __solo->nr_chans))
67#define SOLO_MP4D_EXT_SIZE 0x00080000
68
69#define SOLO_JPEG_EXT_ADDR(__solo) \
70 (SOLO_MP4D_EXT_ADDR(__solo) + \
71 (SOLO_MP4D_EXT_SIZE * __solo->nr_chans))
72#define SOLO_JPEG_EXT_SIZE(__solo) (0x00080000 * __solo->nr_chans)
73 84
74#endif /* __SOLO6X10_OFFSETS_H */ 85#endif /* __SOLO6X10_OFFSETS_H */
diff --git a/drivers/staging/media/solo6x10/osd-font.h b/drivers/staging/media/solo6x10/osd-font.h
deleted file mode 100644
index 591e0e82e0e8..000000000000
--- a/drivers/staging/media/solo6x10/osd-font.h
+++ /dev/null
@@ -1,154 +0,0 @@
1/*
2 * Copyright (C) 2010 Bluecherry, LLC www.bluecherrydvr.com
3 * Copyright (C) 2010 Ben Collins <bcollins@bluecherry.net>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18 */
19
20#ifndef __SOLO6X10_OSD_FONT_H
21#define __SOLO6X10_OSD_FONT_H
22
23static const unsigned int solo_osd_font[] = {
24 0x00000000, 0x0000c0c8, 0xccfefe0c, 0x08000000,
25 0x00000000, 0x10103838, 0x7c7cfefe, 0x00000000, /* 0 */
26 0x00000000, 0xfefe7c7c, 0x38381010, 0x10000000,
27 0x00000000, 0x7c82fefe, 0xfefefe7c, 0x00000000,
28 0x00000000, 0x00001038, 0x10000000, 0x00000000,
29 0x00000000, 0x0010387c, 0xfe7c3810, 0x00000000,
30 0x00000000, 0x00384444, 0x44380000, 0x00000000,
31 0x00000000, 0x38448282, 0x82443800, 0x00000000,
32 0x00000000, 0x007c7c7c, 0x7c7c0000, 0x00000000,
33 0x00000000, 0x6c6c6c6c, 0x6c6c6c6c, 0x00000000,
34 0x00000000, 0x061e7efe, 0xfe7e1e06, 0x00000000,
35 0x00000000, 0xc0f0fcfe, 0xfefcf0c0, 0x00000000,
36 0x00000000, 0xc6cedefe, 0xfedecec6, 0x00000000,
37 0x00000000, 0xc6e6f6fe, 0xfef6e6c6, 0x00000000,
38 0x00000000, 0x12367efe, 0xfe7e3612, 0x00000000,
39 0x00000000, 0x90d8fcfe, 0xfefcd890, 0x00000000,
40 0x00000038, 0x7cc692ba, 0x92c67c38, 0x00000000,
41 0x00000038, 0x7cc6aa92, 0xaac67c38, 0x00000000,
42 0x00000038, 0x7830107c, 0xbaa8680c, 0x00000000,
43 0x00000038, 0x3c18127c, 0xb8382c60, 0x00000000,
44 0x00000044, 0xaa6c8254, 0x38eec67c, 0x00000000,
45 0x00000082, 0x44288244, 0x38c6827c, 0x00000000,
46 0x00000038, 0x444444fe, 0xfeeec6fe, 0x00000000,
47 0x00000018, 0x78187818, 0x3c7e7e3c, 0x00000000,
48 0x00000000, 0x3854929a, 0x82443800, 0x00000000,
49 0x00000000, 0x00c0c8cc, 0xfefe0c08, 0x00000000,
50 0x0000e0a0, 0xe040e00e, 0x8a0ea40e, 0x00000000,
51 0x0000e0a0, 0xe040e00e, 0x0a8e440e, 0x00000000,
52 0x0000007c, 0x82829292, 0x929282fe, 0x00000000,
53 0x000000f8, 0xfc046494, 0x946404fc, 0x00000000,
54 0x0000003f, 0x7f404c52, 0x524c407f, 0x00000000,
55 0x0000007c, 0x82ba82ba, 0x82ba82fe, 0x00000000,
56 0x00000000, 0x00000000, 0x00000000, 0x00000000,
57 0x00000000, 0x183c3c3c, 0x18180018, 0x18000000, /* 32 ! */
58 0x00000066, 0x66240000, 0x00000000, 0x00000000,
59 0x00000000, 0x6c6cfe6c, 0x6c6cfe6c, 0x6c000000, /* 34 " # */
60 0x00001010, 0x7cd6d616, 0x7cd0d6d6, 0x7c101000,
61 0x00000000, 0x0086c660, 0x30180cc6, 0xc2000000, /* 36 $ % */
62 0x00000000, 0x386c6c38, 0xdc766666, 0xdc000000,
63 0x0000000c, 0x0c0c0600, 0x00000000, 0x00000000, /* 38 & ' */
64 0x00000000, 0x30180c0c, 0x0c0c0c18, 0x30000000,
65 0x00000000, 0x0c183030, 0x30303018, 0x0c000000, /* 40 ( ) */
66 0x00000000, 0x0000663c, 0xff3c6600, 0x00000000,
67 0x00000000, 0x00001818, 0x7e181800, 0x00000000, /* 42 * + */
68 0x00000000, 0x00000000, 0x00000e0e, 0x0c060000,
69 0x00000000, 0x00000000, 0x7e000000, 0x00000000, /* 44 , - */
70 0x00000000, 0x00000000, 0x00000006, 0x06000000,
71 0x00000000, 0x80c06030, 0x180c0602, 0x00000000, /* 46 . / */
72 0x0000007c, 0xc6e6f6de, 0xcec6c67c, 0x00000000,
73 0x00000030, 0x383c3030, 0x303030fc, 0x00000000, /* 48 0 1 */
74 0x0000007c, 0xc6c06030, 0x180cc6fe, 0x00000000,
75 0x0000007c, 0xc6c0c07c, 0xc0c0c67c, 0x00000000, /* 50 2 3 */
76 0x00000060, 0x70786c66, 0xfe6060f0, 0x00000000,
77 0x000000fe, 0x0606067e, 0xc0c0c67c, 0x00000000, /* 52 4 5 */
78 0x00000038, 0x0c06067e, 0xc6c6c67c, 0x00000000,
79 0x000000fe, 0xc6c06030, 0x18181818, 0x00000000, /* 54 6 7 */
80 0x0000007c, 0xc6c6c67c, 0xc6c6c67c, 0x00000000,
81 0x0000007c, 0xc6c6c6fc, 0xc0c06038, 0x00000000, /* 56 8 9 */
82 0x00000000, 0x18180000, 0x00181800, 0x00000000,
83 0x00000000, 0x18180000, 0x0018180c, 0x00000000, /* 58 : ; */
84 0x00000060, 0x30180c06, 0x0c183060, 0x00000000,
85 0x00000000, 0x007e0000, 0x007e0000, 0x00000000,
86 0x00000006, 0x0c183060, 0x30180c06, 0x00000000,
87 0x0000007c, 0xc6c66030, 0x30003030, 0x00000000,
88 0x0000007c, 0xc6f6d6d6, 0x7606067c, 0x00000000,
89 0x00000010, 0x386cc6c6, 0xfec6c6c6, 0x00000000, /* 64 @ A */
90 0x0000007e, 0xc6c6c67e, 0xc6c6c67e, 0x00000000,
91 0x00000078, 0xcc060606, 0x0606cc78, 0x00000000, /* 66 */
92 0x0000003e, 0x66c6c6c6, 0xc6c6663e, 0x00000000,
93 0x000000fe, 0x0606063e, 0x060606fe, 0x00000000, /* 68 */
94 0x000000fe, 0x0606063e, 0x06060606, 0x00000000,
95 0x00000078, 0xcc060606, 0xf6c6ccb8, 0x00000000, /* 70 */
96 0x000000c6, 0xc6c6c6fe, 0xc6c6c6c6, 0x00000000,
97 0x0000003c, 0x18181818, 0x1818183c, 0x00000000, /* 72 */
98 0x00000060, 0x60606060, 0x6066663c, 0x00000000,
99 0x000000c6, 0xc666361e, 0x3666c6c6, 0x00000000, /* 74 */
100 0x00000006, 0x06060606, 0x060606fe, 0x00000000,
101 0x000000c6, 0xeefed6c6, 0xc6c6c6c6, 0x00000000, /* 76 */
102 0x000000c6, 0xcedefef6, 0xe6c6c6c6, 0x00000000,
103 0x00000038, 0x6cc6c6c6, 0xc6c66c38, 0x00000000, /* 78 */
104 0x0000007e, 0xc6c6c67e, 0x06060606, 0x00000000,
105 0x00000038, 0x6cc6c6c6, 0xc6d67c38, 0x60000000, /* 80 */
106 0x0000007e, 0xc6c6c67e, 0x66c6c6c6, 0x00000000,
107 0x0000007c, 0xc6c60c38, 0x60c6c67c, 0x00000000, /* 82 */
108 0x0000007e, 0x18181818, 0x18181818, 0x00000000,
109 0x000000c6, 0xc6c6c6c6, 0xc6c6c67c, 0x00000000, /* 84 */
110 0x000000c6, 0xc6c6c6c6, 0xc66c3810, 0x00000000,
111 0x000000c6, 0xc6c6c6c6, 0xd6d6fe6c, 0x00000000, /* 86 */
112 0x000000c6, 0xc6c66c38, 0x6cc6c6c6, 0x00000000,
113 0x00000066, 0x66666666, 0x3c181818, 0x00000000, /* 88 */
114 0x000000fe, 0xc0603018, 0x0c0606fe, 0x00000000,
115 0x0000003c, 0x0c0c0c0c, 0x0c0c0c3c, 0x00000000, /* 90 */
116 0x00000002, 0x060c1830, 0x60c08000, 0x00000000,
117 0x0000003c, 0x30303030, 0x3030303c, 0x00000000, /* 92 */
118 0x00001038, 0x6cc60000, 0x00000000, 0x00000000,
119 0x00000000, 0x00000000, 0x00000000, 0x00fe0000,
120 0x00001818, 0x30000000, 0x00000000, 0x00000000,
121 0x00000000, 0x00003c60, 0x7c66667c, 0x00000000,
122 0x0000000c, 0x0c0c7ccc, 0xcccccc7c, 0x00000000,
123 0x00000000, 0x00007cc6, 0x0606c67c, 0x00000000,
124 0x00000060, 0x60607c66, 0x6666667c, 0x00000000,
125 0x00000000, 0x00007cc6, 0xfe06c67c, 0x00000000,
126 0x00000078, 0x0c0c0c3e, 0x0c0c0c0c, 0x00000000,
127 0x00000000, 0x00007c66, 0x6666667c, 0x60603e00,
128 0x0000000c, 0x0c0c7ccc, 0xcccccccc, 0x00000000,
129 0x00000030, 0x30003830, 0x30303078, 0x00000000,
130 0x00000030, 0x30003c30, 0x30303030, 0x30301f00,
131 0x0000000c, 0x0c0ccc6c, 0x3c6ccccc, 0x00000000,
132 0x00000030, 0x30303030, 0x30303030, 0x00000000,
133 0x00000000, 0x000066fe, 0xd6d6d6d6, 0x00000000,
134 0x00000000, 0x000078cc, 0xcccccccc, 0x00000000,
135 0x00000000, 0x00007cc6, 0xc6c6c67c, 0x00000000,
136 0x00000000, 0x00007ccc, 0xcccccc7c, 0x0c0c0c00,
137 0x00000000, 0x00007c66, 0x6666667c, 0x60606000,
138 0x00000000, 0x000076dc, 0x0c0c0c0c, 0x00000000,
139 0x00000000, 0x00007cc6, 0x1c70c67c, 0x00000000,
140 0x00000000, 0x1818fe18, 0x18181870, 0x00000000,
141 0x00000000, 0x00006666, 0x6666663c, 0x00000000,
142 0x00000000, 0x0000c6c6, 0xc66c3810, 0x00000000,
143 0x00000000, 0x0000c6d6, 0xd6d6fe6c, 0x00000000,
144 0x00000000, 0x0000c66c, 0x38386cc6, 0x00000000,
145 0x00000000, 0x00006666, 0x6666667c, 0x60603e00,
146 0x00000000, 0x0000fe60, 0x30180cfe, 0x00000000,
147 0x00000070, 0x1818180e, 0x18181870, 0x00000000,
148 0x00000018, 0x18181800, 0x18181818, 0x00000000,
149 0x0000000e, 0x18181870, 0x1818180e, 0x00000000,
150 0x000000dc, 0x76000000, 0x00000000, 0x00000000,
151 0x00000000, 0x0010386c, 0xc6c6fe00, 0x00000000
152};
153
154#endif /* __SOLO6X10_OSD_FONT_H */
diff --git a/drivers/staging/media/solo6x10/p2m.c b/drivers/staging/media/solo6x10/p2m.c
index 58ab61b1f1d9..b3a933906b90 100644
--- a/drivers/staging/media/solo6x10/p2m.c
+++ b/drivers/staging/media/solo6x10/p2m.c
@@ -1,6 +1,11 @@
1/* 1/*
2 * Copyright (C) 2010 Bluecherry, LLC www.bluecherrydvr.com 2 * Copyright (C) 2010-2013 Bluecherry, LLC <http://www.bluecherrydvr.com>
3 * Copyright (C) 2010 Ben Collins <bcollins@bluecherry.net> 3 *
4 * Original author:
5 * Ben Collins <bcollins@ubuntu.com>
6 *
7 * Additional work by:
8 * John Brooks <john.brooks@bluecherry.net>
4 * 9 *
5 * This program is free software; you can redistribute it and/or modify 10 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by 11 * it under the terms of the GNU General Public License as published by
@@ -18,28 +23,38 @@
18 */ 23 */
19 24
20#include <linux/kernel.h> 25#include <linux/kernel.h>
26#include <linux/module.h>
21#include <linux/slab.h> 27#include <linux/slab.h>
22#include <linux/scatterlist.h> 28
23#include "solo6x10.h" 29#include "solo6x10.h"
24 30
25/* #define SOLO_TEST_P2M */ 31static int multi_p2m;
32module_param(multi_p2m, uint, 0644);
33MODULE_PARM_DESC(multi_p2m,
34 "Use multiple P2M DMA channels (default: no, 6010-only)");
26 35
27int solo_p2m_dma(struct solo_dev *solo_dev, u8 id, int wr, 36static int desc_mode;
28 void *sys_addr, u32 ext_addr, u32 size) 37module_param(desc_mode, uint, 0644);
38MODULE_PARM_DESC(desc_mode,
39 "Allow use of descriptor mode DMA (default: no, 6010-only)");
40
41int solo_p2m_dma(struct solo_dev *solo_dev, int wr,
42 void *sys_addr, u32 ext_addr, u32 size,
43 int repeat, u32 ext_size)
29{ 44{
30 dma_addr_t dma_addr; 45 dma_addr_t dma_addr;
31 int ret; 46 int ret;
32 47
33 WARN_ON(!size); 48 if (WARN_ON_ONCE((unsigned long)sys_addr & 0x03))
34 BUG_ON(id >= SOLO_NR_P2M); 49 return -EINVAL;
35 50 if (WARN_ON_ONCE(!size))
36 if (!size)
37 return -EINVAL; 51 return -EINVAL;
38 52
39 dma_addr = pci_map_single(solo_dev->pdev, sys_addr, size, 53 dma_addr = pci_map_single(solo_dev->pdev, sys_addr, size,
40 wr ? PCI_DMA_TODEVICE : PCI_DMA_FROMDEVICE); 54 wr ? PCI_DMA_TODEVICE : PCI_DMA_FROMDEVICE);
41 55
42 ret = solo_p2m_dma_t(solo_dev, id, wr, dma_addr, ext_addr, size); 56 ret = solo_p2m_dma_t(solo_dev, wr, dma_addr, ext_addr, size,
57 repeat, ext_size);
43 58
44 pci_unmap_single(solo_dev->pdev, dma_addr, size, 59 pci_unmap_single(solo_dev->pdev, dma_addr, size,
45 wr ? PCI_DMA_TODEVICE : PCI_DMA_FROMDEVICE); 60 wr ? PCI_DMA_TODEVICE : PCI_DMA_FROMDEVICE);
@@ -47,221 +62,141 @@ int solo_p2m_dma(struct solo_dev *solo_dev, u8 id, int wr,
47 return ret; 62 return ret;
48} 63}
49 64
50int solo_p2m_dma_t(struct solo_dev *solo_dev, u8 id, int wr, 65/* Mutex must be held for p2m_id before calling this!! */
51 dma_addr_t dma_addr, u32 ext_addr, u32 size) 66int solo_p2m_dma_desc(struct solo_dev *solo_dev,
52{ 67 struct solo_p2m_desc *desc, dma_addr_t desc_dma,
53 struct p2m_desc *desc = kzalloc(sizeof(*desc) * 2, GFP_DMA); 68 int desc_cnt)
54 int ret;
55
56 if (desc == NULL)
57 return -ENOMEM;
58
59 solo_p2m_push_desc(&desc[1], wr, dma_addr, ext_addr, size, 0, 0);
60 ret = solo_p2m_dma_desc(solo_dev, id, desc, 2);
61 kfree(desc);
62
63 return ret;
64}
65
66void solo_p2m_push_desc(struct p2m_desc *desc, int wr, dma_addr_t dma_addr,
67 u32 ext_addr, u32 size, int repeat, u32 ext_size)
68{
69 desc->ta = cpu_to_le32(dma_addr);
70 desc->fa = cpu_to_le32(ext_addr);
71
72 desc->ext = cpu_to_le32(SOLO_P2M_COPY_SIZE(size >> 2));
73 desc->ctrl = cpu_to_le32(SOLO_P2M_BURST_SIZE(SOLO_P2M_BURST_256) |
74 (wr ? SOLO_P2M_WRITE : 0) | SOLO_P2M_TRANS_ON);
75
76 /* Ext size only matters when we're repeating */
77 if (repeat) {
78 desc->ext |= cpu_to_le32(SOLO_P2M_EXT_INC(ext_size >> 2));
79 desc->ctrl |= cpu_to_le32(SOLO_P2M_PCI_INC(size >> 2) |
80 SOLO_P2M_REPEAT(repeat));
81 }
82}
83
84int solo_p2m_dma_desc(struct solo_dev *solo_dev, u8 id,
85 struct p2m_desc *desc, int desc_count)
86{ 69{
87 struct solo_p2m_dev *p2m_dev; 70 struct solo_p2m_dev *p2m_dev;
88 unsigned int timeout; 71 unsigned int timeout;
72 unsigned int config = 0;
89 int ret = 0; 73 int ret = 0;
90 u32 config = 0; 74 int p2m_id = 0;
91 dma_addr_t desc_dma = 0;
92 75
93 BUG_ON(id >= SOLO_NR_P2M); 76 /* Get next ID. According to Softlogic, 6110 has problems on !=0 P2M */
94 BUG_ON(!desc_count || desc_count > SOLO_NR_P2M_DESC); 77 if (solo_dev->type != SOLO_DEV_6110 && multi_p2m) {
78 p2m_id = atomic_inc_return(&solo_dev->p2m_count) % SOLO_NR_P2M;
79 if (p2m_id < 0)
80 p2m_id = -p2m_id;
81 }
95 82
96 p2m_dev = &solo_dev->p2m_dev[id]; 83 p2m_dev = &solo_dev->p2m_dev[p2m_id];
97 84
98 mutex_lock(&p2m_dev->mutex); 85 if (mutex_lock_interruptible(&p2m_dev->mutex))
99 86 return -EINTR;
100 solo_reg_write(solo_dev, SOLO_P2M_CONTROL(id), 0);
101 87
102 INIT_COMPLETION(p2m_dev->completion); 88 INIT_COMPLETION(p2m_dev->completion);
103 p2m_dev->error = 0; 89 p2m_dev->error = 0;
104 90
105 /* Enable the descriptors */ 91 if (desc_cnt > 1 && solo_dev->type != SOLO_DEV_6110 && desc_mode) {
106 config = solo_reg_read(solo_dev, SOLO_P2M_CONFIG(id)); 92 /* For 6010 with more than one desc, we can do a one-shot */
107 desc_dma = pci_map_single(solo_dev->pdev, desc, 93 p2m_dev->desc_count = p2m_dev->desc_idx = 0;
108 desc_count * sizeof(*desc), 94 config = solo_reg_read(solo_dev, SOLO_P2M_CONFIG(p2m_id));
109 PCI_DMA_TODEVICE); 95
110 solo_reg_write(solo_dev, SOLO_P2M_DES_ADR(id), desc_dma); 96 solo_reg_write(solo_dev, SOLO_P2M_DES_ADR(p2m_id), desc_dma);
111 solo_reg_write(solo_dev, SOLO_P2M_DESC_ID(id), desc_count - 1); 97 solo_reg_write(solo_dev, SOLO_P2M_DESC_ID(p2m_id), desc_cnt);
112 solo_reg_write(solo_dev, SOLO_P2M_CONFIG(id), config | 98 solo_reg_write(solo_dev, SOLO_P2M_CONFIG(p2m_id), config |
113 SOLO_P2M_DESC_MODE); 99 SOLO_P2M_DESC_MODE);
114 100 } else {
115 /* Should have all descriptors completed from one interrupt */ 101 /* For single descriptors and 6110, we need to run each desc */
116 timeout = wait_for_completion_timeout(&p2m_dev->completion, HZ); 102 p2m_dev->desc_count = desc_cnt;
117 103 p2m_dev->desc_idx = 1;
118 solo_reg_write(solo_dev, SOLO_P2M_CONTROL(id), 0); 104 p2m_dev->descs = desc;
105
106 solo_reg_write(solo_dev, SOLO_P2M_TAR_ADR(p2m_id),
107 desc[1].dma_addr);
108 solo_reg_write(solo_dev, SOLO_P2M_EXT_ADR(p2m_id),
109 desc[1].ext_addr);
110 solo_reg_write(solo_dev, SOLO_P2M_EXT_CFG(p2m_id),
111 desc[1].cfg);
112 solo_reg_write(solo_dev, SOLO_P2M_CONTROL(p2m_id),
113 desc[1].ctrl);
114 }
119 115
120 /* Reset back to non-descriptor mode */ 116 timeout = wait_for_completion_timeout(&p2m_dev->completion,
121 solo_reg_write(solo_dev, SOLO_P2M_CONFIG(id), config); 117 solo_dev->p2m_jiffies);
122 solo_reg_write(solo_dev, SOLO_P2M_DESC_ID(id), 0);
123 solo_reg_write(solo_dev, SOLO_P2M_DES_ADR(id), 0);
124 pci_unmap_single(solo_dev->pdev, desc_dma,
125 desc_count * sizeof(*desc),
126 PCI_DMA_TODEVICE);
127 118
128 if (p2m_dev->error) 119 if (WARN_ON_ONCE(p2m_dev->error))
129 ret = -EIO; 120 ret = -EIO;
130 else if (timeout == 0) 121 else if (timeout == 0) {
122 solo_dev->p2m_timeouts++;
131 ret = -EAGAIN; 123 ret = -EAGAIN;
132
133 mutex_unlock(&p2m_dev->mutex);
134
135 WARN_ON_ONCE(ret);
136
137 return ret;
138}
139
140int solo_p2m_dma_sg(struct solo_dev *solo_dev, u8 id,
141 struct p2m_desc *pdesc, int wr,
142 struct scatterlist *sg, u32 sg_off,
143 u32 ext_addr, u32 size)
144{
145 int i;
146 int idx;
147
148 BUG_ON(id >= SOLO_NR_P2M);
149
150 if (WARN_ON_ONCE(!size))
151 return -EINVAL;
152
153 memset(pdesc, 0, sizeof(*pdesc));
154
155 /* Should rewrite this to handle > SOLO_NR_P2M_DESC transactions */
156 for (i = 0, idx = 1; idx < SOLO_NR_P2M_DESC && sg && size > 0;
157 i++, sg = sg_next(sg)) {
158 struct p2m_desc *desc = &pdesc[idx];
159 u32 sg_len = sg_dma_len(sg);
160 u32 len;
161
162 if (sg_off >= sg_len) {
163 sg_off -= sg_len;
164 continue;
165 }
166
167 sg_len -= sg_off;
168 len = min(sg_len, size);
169
170 solo_p2m_push_desc(desc, wr, sg_dma_address(sg) + sg_off,
171 ext_addr, len, 0, 0);
172
173 size -= len;
174 ext_addr += len;
175 idx++;
176
177 sg_off = 0;
178 } 124 }
179 125
180 WARN_ON_ONCE(size || i >= SOLO_NR_P2M_DESC); 126 solo_reg_write(solo_dev, SOLO_P2M_CONTROL(p2m_id), 0);
181 127
182 return solo_p2m_dma_desc(solo_dev, id, pdesc, idx); 128 /* Don't write here for the no_desc_mode case, because config is 0.
183} 129 * We can't test no_desc_mode again, it might race. */
130 if (desc_cnt > 1 && solo_dev->type != SOLO_DEV_6110 && config)
131 solo_reg_write(solo_dev, SOLO_P2M_CONFIG(p2m_id), config);
184 132
185#ifdef SOLO_TEST_P2M 133 mutex_unlock(&p2m_dev->mutex);
186 134
187#define P2M_TEST_CHAR 0xbe 135 return ret;
136}
188 137
189static unsigned long long p2m_test(struct solo_dev *solo_dev, u8 id, 138void solo_p2m_fill_desc(struct solo_p2m_desc *desc, int wr,
190 u32 base, int size) 139 dma_addr_t dma_addr, u32 ext_addr, u32 size,
140 int repeat, u32 ext_size)
191{ 141{
192 u8 *wr_buf; 142 WARN_ON_ONCE(dma_addr & 0x03);
193 u8 *rd_buf; 143 WARN_ON_ONCE(!size);
194 int i;
195 unsigned long long err_cnt = 0;
196 144
197 wr_buf = kmalloc(size, GFP_KERNEL); 145 desc->cfg = SOLO_P2M_COPY_SIZE(size >> 2);
198 if (!wr_buf) { 146 desc->ctrl = SOLO_P2M_BURST_SIZE(SOLO_P2M_BURST_256) |
199 printk(SOLO6X10_NAME ": Failed to malloc for p2m_test\n"); 147 (wr ? SOLO_P2M_WRITE : 0) | SOLO_P2M_TRANS_ON;
200 return size;
201 }
202 148
203 rd_buf = kmalloc(size, GFP_KERNEL); 149 if (repeat) {
204 if (!rd_buf) { 150 desc->cfg |= SOLO_P2M_EXT_INC(ext_size >> 2);
205 printk(SOLO6X10_NAME ": Failed to malloc for p2m_test\n"); 151 desc->ctrl |= SOLO_P2M_PCI_INC(size >> 2) |
206 kfree(wr_buf); 152 SOLO_P2M_REPEAT(repeat);
207 return size;
208 } 153 }
209 154
210 memset(wr_buf, P2M_TEST_CHAR, size); 155 desc->dma_addr = dma_addr;
211 memset(rd_buf, P2M_TEST_CHAR + 1, size); 156 desc->ext_addr = ext_addr;
212
213 solo_p2m_dma(solo_dev, id, 1, wr_buf, base, size);
214 solo_p2m_dma(solo_dev, id, 0, rd_buf, base, size);
215
216 for (i = 0; i < size; i++)
217 if (wr_buf[i] != rd_buf[i])
218 err_cnt++;
219
220 kfree(wr_buf);
221 kfree(rd_buf);
222
223 return err_cnt;
224} 157}
225 158
226#define TEST_CHUNK_SIZE (8 * 1024) 159int solo_p2m_dma_t(struct solo_dev *solo_dev, int wr,
227 160 dma_addr_t dma_addr, u32 ext_addr, u32 size,
228static void run_p2m_test(struct solo_dev *solo_dev) 161 int repeat, u32 ext_size)
229{ 162{
230 unsigned long long errs = 0; 163 struct solo_p2m_desc desc[2];
231 u32 size = SOLO_JPEG_EXT_ADDR(solo_dev) + SOLO_JPEG_EXT_SIZE(solo_dev);
232 int i, d;
233 164
234 dev_warn(&solo_dev->pdev->dev, "Testing %u bytes of external ram\n", 165 solo_p2m_fill_desc(&desc[1], wr, dma_addr, ext_addr, size, repeat,
235 size); 166 ext_size);
236 167
237 for (i = 0; i < size; i += TEST_CHUNK_SIZE) 168 /* No need for desc_dma since we know it is a single-shot */
238 for (d = 0; d < 4; d++) 169 return solo_p2m_dma_desc(solo_dev, desc, 0, 1);
239 errs += p2m_test(solo_dev, d, i, TEST_CHUNK_SIZE);
240
241 dev_warn(&solo_dev->pdev->dev, "Found %llu errors during p2m test\n",
242 errs);
243
244 return;
245} 170}
246#else
247#define run_p2m_test(__solo) do {} while (0)
248#endif
249 171
250void solo_p2m_isr(struct solo_dev *solo_dev, int id) 172void solo_p2m_isr(struct solo_dev *solo_dev, int id)
251{ 173{
252 struct solo_p2m_dev *p2m_dev = &solo_dev->p2m_dev[id]; 174 struct solo_p2m_dev *p2m_dev = &solo_dev->p2m_dev[id];
175 struct solo_p2m_desc *desc;
176
177 if (p2m_dev->desc_count <= p2m_dev->desc_idx) {
178 complete(&p2m_dev->completion);
179 return;
180 }
253 181
254 solo_reg_write(solo_dev, SOLO_IRQ_STAT, SOLO_IRQ_P2M(id)); 182 /* Setup next descriptor */
183 p2m_dev->desc_idx++;
184 desc = &p2m_dev->descs[p2m_dev->desc_idx];
255 185
256 complete(&p2m_dev->completion); 186 solo_reg_write(solo_dev, SOLO_P2M_CONTROL(id), 0);
187 solo_reg_write(solo_dev, SOLO_P2M_TAR_ADR(id), desc->dma_addr);
188 solo_reg_write(solo_dev, SOLO_P2M_EXT_ADR(id), desc->ext_addr);
189 solo_reg_write(solo_dev, SOLO_P2M_EXT_CFG(id), desc->cfg);
190 solo_reg_write(solo_dev, SOLO_P2M_CONTROL(id), desc->ctrl);
257} 191}
258 192
259void solo_p2m_error_isr(struct solo_dev *solo_dev, u32 status) 193void solo_p2m_error_isr(struct solo_dev *solo_dev)
260{ 194{
195 unsigned int err = solo_reg_read(solo_dev, SOLO_PCI_ERR);
261 struct solo_p2m_dev *p2m_dev; 196 struct solo_p2m_dev *p2m_dev;
262 int i; 197 int i;
263 198
264 if (!(status & SOLO_PCI_ERR_P2M)) 199 if (!(err & SOLO_PCI_ERR_P2M))
265 return; 200 return;
266 201
267 for (i = 0; i < SOLO_NR_P2M; i++) { 202 for (i = 0; i < SOLO_NR_P2M; i++) {
@@ -280,6 +215,52 @@ void solo_p2m_exit(struct solo_dev *solo_dev)
280 solo_irq_off(solo_dev, SOLO_IRQ_P2M(i)); 215 solo_irq_off(solo_dev, SOLO_IRQ_P2M(i));
281} 216}
282 217
218static int solo_p2m_test(struct solo_dev *solo_dev, int base, int size)
219{
220 u32 *wr_buf;
221 u32 *rd_buf;
222 int i;
223 int ret = -EIO;
224 int order = get_order(size);
225
226 wr_buf = (u32 *)__get_free_pages(GFP_KERNEL, order);
227 if (wr_buf == NULL)
228 return -1;
229
230 rd_buf = (u32 *)__get_free_pages(GFP_KERNEL, order);
231 if (rd_buf == NULL) {
232 free_pages((unsigned long)wr_buf, order);
233 return -1;
234 }
235
236 for (i = 0; i < (size >> 3); i++)
237 *(wr_buf + i) = (i << 16) | (i + 1);
238
239 for (i = (size >> 3); i < (size >> 2); i++)
240 *(wr_buf + i) = ~((i << 16) | (i + 1));
241
242 memset(rd_buf, 0x55, size);
243
244 if (solo_p2m_dma(solo_dev, 1, wr_buf, base, size, 0, 0))
245 goto test_fail;
246
247 if (solo_p2m_dma(solo_dev, 0, rd_buf, base, size, 0, 0))
248 goto test_fail;
249
250 for (i = 0; i < (size >> 2); i++) {
251 if (*(wr_buf + i) != *(rd_buf + i))
252 goto test_fail;
253 }
254
255 ret = 0;
256
257test_fail:
258 free_pages((unsigned long)wr_buf, order);
259 free_pages((unsigned long)rd_buf, order);
260
261 return ret;
262}
263
283int solo_p2m_init(struct solo_dev *solo_dev) 264int solo_p2m_init(struct solo_dev *solo_dev)
284{ 265{
285 struct solo_p2m_dev *p2m_dev; 266 struct solo_p2m_dev *p2m_dev;
@@ -294,13 +275,57 @@ int solo_p2m_init(struct solo_dev *solo_dev)
294 solo_reg_write(solo_dev, SOLO_P2M_CONTROL(i), 0); 275 solo_reg_write(solo_dev, SOLO_P2M_CONTROL(i), 0);
295 solo_reg_write(solo_dev, SOLO_P2M_CONFIG(i), 276 solo_reg_write(solo_dev, SOLO_P2M_CONFIG(i),
296 SOLO_P2M_CSC_16BIT_565 | 277 SOLO_P2M_CSC_16BIT_565 |
297 SOLO_P2M_DMA_INTERVAL(3) |
298 SOLO_P2M_DESC_INTR_OPT | 278 SOLO_P2M_DESC_INTR_OPT |
279 SOLO_P2M_DMA_INTERVAL(0) |
299 SOLO_P2M_PCI_MASTER_MODE); 280 SOLO_P2M_PCI_MASTER_MODE);
300 solo_irq_on(solo_dev, SOLO_IRQ_P2M(i)); 281 solo_irq_on(solo_dev, SOLO_IRQ_P2M(i));
301 } 282 }
302 283
303 run_p2m_test(solo_dev); 284 /* Find correct SDRAM size */
285 for (solo_dev->sdram_size = 0, i = 2; i >= 0; i--) {
286 solo_reg_write(solo_dev, SOLO_DMA_CTRL,
287 SOLO_DMA_CTRL_REFRESH_CYCLE(1) |
288 SOLO_DMA_CTRL_SDRAM_SIZE(i) |
289 SOLO_DMA_CTRL_SDRAM_CLK_INVERT |
290 SOLO_DMA_CTRL_READ_CLK_SELECT |
291 SOLO_DMA_CTRL_LATENCY(1));
292
293 solo_reg_write(solo_dev, SOLO_SYS_CFG, solo_dev->sys_config |
294 SOLO_SYS_CFG_RESET);
295 solo_reg_write(solo_dev, SOLO_SYS_CFG, solo_dev->sys_config);
296
297 switch (i) {
298 case 2:
299 if (solo_p2m_test(solo_dev, 0x07ff0000, 0x00010000) ||
300 solo_p2m_test(solo_dev, 0x05ff0000, 0x00010000))
301 continue;
302 break;
303
304 case 1:
305 if (solo_p2m_test(solo_dev, 0x03ff0000, 0x00010000))
306 continue;
307 break;
308
309 default:
310 if (solo_p2m_test(solo_dev, 0x01ff0000, 0x00010000))
311 continue;
312 }
313
314 solo_dev->sdram_size = (32 << 20) << i;
315 break;
316 }
317
318 if (!solo_dev->sdram_size) {
319 dev_err(&solo_dev->pdev->dev, "Error detecting SDRAM size\n");
320 return -EIO;
321 }
322
323 if (SOLO_SDRAM_END(solo_dev) > solo_dev->sdram_size) {
324 dev_err(&solo_dev->pdev->dev,
325 "SDRAM is not large enough (%u < %u)\n",
326 solo_dev->sdram_size, SOLO_SDRAM_END(solo_dev));
327 return -EIO;
328 }
304 329
305 return 0; 330 return 0;
306} 331}
diff --git a/drivers/staging/media/solo6x10/registers.h b/drivers/staging/media/solo6x10/registers.h
index aca544472c93..5e5c7e6b43bf 100644
--- a/drivers/staging/media/solo6x10/registers.h
+++ b/drivers/staging/media/solo6x10/registers.h
@@ -1,6 +1,11 @@
1/* 1/*
2 * Copyright (C) 2010 Bluecherry, LLC www.bluecherrydvr.com 2 * Copyright (C) 2010-2013 Bluecherry, LLC <http://www.bluecherrydvr.com>
3 * Copyright (C) 2010 Ben Collins <bcollins@bluecherry.net> 3 *
4 * Original author:
5 * Ben Collins <bcollins@ubuntu.com>
6 *
7 * Additional work by:
8 * John Brooks <john.brooks@bluecherry.net>
4 * 9 *
5 * This program is free software; you can redistribute it and/or modify 10 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by 11 * it under the terms of the GNU General Public License as published by
@@ -22,18 +27,18 @@
22 27
23#include "offsets.h" 28#include "offsets.h"
24 29
25/* Global 6X10 system configuration */ 30/* Global 6010 system configuration */
26#define SOLO_SYS_CFG 0x0000 31#define SOLO_SYS_CFG 0x0000
27#define SOLO6010_SYS_CFG_FOUT_EN 0x00000001 /* 6010 only */ 32#define SOLO_SYS_CFG_FOUT_EN 0x00000001
28#define SOLO6010_SYS_CFG_PLL_BYPASS 0x00000002 /* 6010 only */ 33#define SOLO_SYS_CFG_PLL_BYPASS 0x00000002
29#define SOLO6010_SYS_CFG_PLL_PWDN 0x00000004 /* 6010 only */ 34#define SOLO_SYS_CFG_PLL_PWDN 0x00000004
30#define SOLO6010_SYS_CFG_OUTDIV(__n) (((__n) & 0x003) << 3) /* 6010 only */ 35#define SOLO_SYS_CFG_OUTDIV(__n) (((__n) & 0x003) << 3)
31#define SOLO6010_SYS_CFG_FEEDBACKDIV(__n) (((__n) & 0x1ff) << 5) /* 6010 only */ 36#define SOLO_SYS_CFG_FEEDBACKDIV(__n) (((__n) & 0x1ff) << 5)
32#define SOLO6010_SYS_CFG_INPUTDIV(__n) (((__n) & 0x01f) << 14) /* 6010 only */ 37#define SOLO_SYS_CFG_INPUTDIV(__n) (((__n) & 0x01f) << 14)
33#define SOLO_SYS_CFG_CLOCK_DIV 0x00080000 38#define SOLO_SYS_CFG_CLOCK_DIV 0x00080000
34#define SOLO_SYS_CFG_NCLK_DELAY(__n) (((__n) & 0x003) << 24) 39#define SOLO_SYS_CFG_NCLK_DELAY(__n) (((__n) & 0x003) << 24)
35#define SOLO_SYS_CFG_PCLK_DELAY(__n) (((__n) & 0x00f) << 26) 40#define SOLO_SYS_CFG_PCLK_DELAY(__n) (((__n) & 0x00f) << 26)
36#define SOLO_SYS_CFG_SDRAM64BIT 0x40000000 /* 6110: must be set */ 41#define SOLO_SYS_CFG_SDRAM64BIT 0x40000000
37#define SOLO_SYS_CFG_RESET 0x80000000 42#define SOLO_SYS_CFG_RESET 0x80000000
38 43
39#define SOLO_DMA_CTRL 0x0004 44#define SOLO_DMA_CTRL 0x0004
@@ -45,7 +50,9 @@
45#define SOLO_DMA_CTRL_READ_DATA_SELECT (1<<3) 50#define SOLO_DMA_CTRL_READ_DATA_SELECT (1<<3)
46#define SOLO_DMA_CTRL_READ_CLK_SELECT (1<<2) 51#define SOLO_DMA_CTRL_READ_CLK_SELECT (1<<2)
47#define SOLO_DMA_CTRL_LATENCY(n) ((n)<<0) 52#define SOLO_DMA_CTRL_LATENCY(n) ((n)<<0)
48#define SOLO_DMA_CTRL1 0x0008 53
54/* Some things we set in this are undocumented. Why Softlogic?!?! */
55#define SOLO_DMA_CTRL1 0x0008
49 56
50#define SOLO_SYS_VCLK 0x000C 57#define SOLO_SYS_VCLK 0x000C
51#define SOLO_VCLK_INVERT (1<<22) 58#define SOLO_VCLK_INVERT (1<<22)
@@ -61,7 +68,7 @@
61#define SOLO_VCLK_VIN0001_DELAY(n) ((n)<<0) 68#define SOLO_VCLK_VIN0001_DELAY(n) ((n)<<0)
62 69
63#define SOLO_IRQ_STAT 0x0010 70#define SOLO_IRQ_STAT 0x0010
64#define SOLO_IRQ_ENABLE 0x0014 71#define SOLO_IRQ_MASK 0x0014
65#define SOLO_IRQ_P2M(n) (1<<((n)+17)) 72#define SOLO_IRQ_P2M(n) (1<<((n)+17))
66#define SOLO_IRQ_GPIO (1<<16) 73#define SOLO_IRQ_GPIO (1<<16)
67#define SOLO_IRQ_VIDEO_LOSS (1<<15) 74#define SOLO_IRQ_VIDEO_LOSS (1<<15)
@@ -82,22 +89,7 @@
82#define SOLO_CHIP_OPTION 0x001C 89#define SOLO_CHIP_OPTION 0x001C
83#define SOLO_CHIP_ID_MASK 0x00000007 90#define SOLO_CHIP_ID_MASK 0x00000007
84 91
85#define SOLO6110_PLL_CONFIG 0x0020 92#define SOLO_PLL_CONFIG 0x0020 /* 6110 Only */
86#define SOLO6110_PLL_RANGE_BYPASS (0 << 20)
87#define SOLO6110_PLL_RANGE_5_10MHZ (1 << 20)
88#define SOLO6110_PLL_RANGE_8_16MHZ (2 << 20)
89#define SOLO6110_PLL_RANGE_13_26MHZ (3 << 20)
90#define SOLO6110_PLL_RANGE_21_42MHZ (4 << 20)
91#define SOLO6110_PLL_RANGE_34_68MHZ (5 << 20)
92#define SOLO6110_PLL_RANGE_54_108MHZ (6 << 20)
93#define SOLO6110_PLL_RANGE_88_200MHZ (7 << 20)
94#define SOLO6110_PLL_DIVR(x) (((x) - 1) << 15)
95#define SOLO6110_PLL_DIVQ_EXP(x) ((x) << 12)
96#define SOLO6110_PLL_DIVF(x) (((x) - 1) << 4)
97#define SOLO6110_PLL_RESET (1 << 3)
98#define SOLO6110_PLL_BYPASS (1 << 2)
99#define SOLO6110_PLL_FSEN (1 << 1)
100#define SOLO6110_PLL_FB (1 << 0)
101 93
102#define SOLO_EEPROM_CTRL 0x0060 94#define SOLO_EEPROM_CTRL 0x0060
103#define SOLO_EEPROM_ACCESS_EN (1<<7) 95#define SOLO_EEPROM_ACCESS_EN (1<<7)
@@ -105,7 +97,7 @@
105#define SOLO_EEPROM_CLK (1<<2) 97#define SOLO_EEPROM_CLK (1<<2)
106#define SOLO_EEPROM_DO (1<<1) 98#define SOLO_EEPROM_DO (1<<1)
107#define SOLO_EEPROM_DI (1<<0) 99#define SOLO_EEPROM_DI (1<<0)
108#define SOLO_EEPROM_ENABLE (EEPROM_ACCESS_EN | EEPROM_CS) 100#define SOLO_EEPROM_ENABLE (SOLO_EEPROM_ACCESS_EN | SOLO_EEPROM_CS)
109 101
110#define SOLO_PCI_ERR 0x0070 102#define SOLO_PCI_ERR 0x0070
111#define SOLO_PCI_ERR_FATAL 0x00000001 103#define SOLO_PCI_ERR_FATAL 0x00000001
@@ -274,8 +266,8 @@
274#define SOLO_VO_FI_CHANGE (1<<20) 266#define SOLO_VO_FI_CHANGE (1<<20)
275#define SOLO_VO_USER_COLOR_SET_VSYNC (1<<19) 267#define SOLO_VO_USER_COLOR_SET_VSYNC (1<<19)
276#define SOLO_VO_USER_COLOR_SET_HSYNC (1<<18) 268#define SOLO_VO_USER_COLOR_SET_HSYNC (1<<18)
277#define SOLO_VO_USER_COLOR_SET_NAV (1<<17) 269#define SOLO_VO_USER_COLOR_SET_NAH (1<<17)
278#define SOLO_VO_USER_COLOR_SET_NAH (1<<16) 270#define SOLO_VO_USER_COLOR_SET_NAV (1<<16)
279#define SOLO_VO_NA_COLOR_Y(Y) ((Y)<<8) 271#define SOLO_VO_NA_COLOR_Y(Y) ((Y)<<8)
280#define SOLO_VO_NA_COLOR_CB(CB) (((CB)/16)<<4) 272#define SOLO_VO_NA_COLOR_CB(CB) (((CB)/16)<<4)
281#define SOLO_VO_NA_COLOR_CR(CR) (((CR)/16)<<0) 273#define SOLO_VO_NA_COLOR_CR(CR) (((CR)/16)<<0)
@@ -401,12 +393,13 @@
401#define SOLO_VE_BLOCK_BASE(n) ((n)<<0) 393#define SOLO_VE_BLOCK_BASE(n) ((n)<<0)
402 394
403#define SOLO_VE_CFG1 0x0614 395#define SOLO_VE_CFG1 0x0614
404#define SOLO6110_VE_MPEG_SIZE_H(n) ((n)<<28) /* 6110 only */ 396#define SOLO_VE_BYTE_ALIGN(n) ((n)<<24)
405#define SOLO6010_VE_BYTE_ALIGN(n) ((n)<<24) /* 6010 only */
406#define SOLO6110_VE_JPEG_SIZE_H(n) ((n)<<20) /* 6110 only */
407#define SOLO_VE_INSERT_INDEX (1<<18) 397#define SOLO_VE_INSERT_INDEX (1<<18)
408#define SOLO_VE_MOTION_MODE(n) ((n)<<16) 398#define SOLO_VE_MOTION_MODE(n) ((n)<<16)
409#define SOLO_VE_MOTION_BASE(n) ((n)<<0) 399#define SOLO_VE_MOTION_BASE(n) ((n)<<0)
400#define SOLO_VE_MPEG_SIZE_H(n) ((n)<<28) /* 6110 Only */
401#define SOLO_VE_JPEG_SIZE_H(n) ((n)<<20) /* 6110 Only */
402#define SOLO_VE_INSERT_INDEX_JPEG (1<<19) /* 6110 Only */
410 403
411#define SOLO_VE_WMRK_POLY 0x061C 404#define SOLO_VE_WMRK_POLY 0x061C
412#define SOLO_VE_VMRK_INIT_KEY 0x0620 405#define SOLO_VE_VMRK_INIT_KEY 0x0620
@@ -420,6 +413,7 @@
420#define SOLO_COMP_TIME_INC(n) ((n)<<25) 413#define SOLO_COMP_TIME_INC(n) ((n)<<25)
421#define SOLO_COMP_TIME_WIDTH(n) ((n)<<21) 414#define SOLO_COMP_TIME_WIDTH(n) ((n)<<21)
422#define SOLO_DCT_INTERVAL(n) ((n)<<16) 415#define SOLO_DCT_INTERVAL(n) ((n)<<16)
416#define SOLO_VE_COMPT_MOT 0x0634 /* 6110 Only */
423 417
424#define SOLO_VE_STATE(n) (0x0640+((n)*4)) 418#define SOLO_VE_STATE(n) (0x0640+((n)*4))
425 419
@@ -428,14 +422,21 @@
428#define SOLO_VE_JPEG_QP_CH_H 0x0678 422#define SOLO_VE_JPEG_QP_CH_H 0x0678
429#define SOLO_VE_JPEG_CFG 0x067C 423#define SOLO_VE_JPEG_CFG 0x067C
430#define SOLO_VE_JPEG_CTRL 0x0680 424#define SOLO_VE_JPEG_CTRL 0x0680
431 425#define SOLO_VE_CODE_ENCRYPT 0x0684 /* 6110 Only */
426#define SOLO_VE_JPEG_CFG1 0x0688 /* 6110 Only */
427#define SOLO_VE_WMRK_ENABLE 0x068C /* 6110 Only */
432#define SOLO_VE_OSD_CH 0x0690 428#define SOLO_VE_OSD_CH 0x0690
433#define SOLO_VE_OSD_BASE 0x0694 429#define SOLO_VE_OSD_BASE 0x0694
434#define SOLO_VE_OSD_CLR 0x0698 430#define SOLO_VE_OSD_CLR 0x0698
435#define SOLO_VE_OSD_OPT 0x069C 431#define SOLO_VE_OSD_OPT 0x069C
432#define SOLO_VE_OSD_V_DOUBLE (1<<16) /* 6110 Only */
433#define SOLO_VE_OSD_H_SHADOW (1<<15)
434#define SOLO_VE_OSD_V_SHADOW (1<<14)
435#define SOLO_VE_OSD_H_OFFSET(n) ((n & 0x7f)<<7)
436#define SOLO_VE_OSD_V_OFFSET(n) (n & 0x7f)
436 437
437#define SOLO_VE_CH_INTL(ch) (0x0700+((ch)*4)) 438#define SOLO_VE_CH_INTL(ch) (0x0700+((ch)*4))
438#define SOLO6010_VE_CH_MOT(ch) (0x0740+((ch)*4)) /* 6010 only */ 439#define SOLO_VE_CH_MOT(ch) (0x0740+((ch)*4))
439#define SOLO_VE_CH_QP(ch) (0x0780+((ch)*4)) 440#define SOLO_VE_CH_QP(ch) (0x0780+((ch)*4))
440#define SOLO_VE_CH_QP_E(ch) (0x07C0+((ch)*4)) 441#define SOLO_VE_CH_QP_E(ch) (0x07C0+((ch)*4))
441#define SOLO_VE_CH_GOP(ch) (0x0800+((ch)*4)) 442#define SOLO_VE_CH_GOP(ch) (0x0800+((ch)*4))
@@ -447,7 +448,7 @@
447#define SOLO_VE_JPEG_QUE(n) (0x0A04+((n)*8)) 448#define SOLO_VE_JPEG_QUE(n) (0x0A04+((n)*8))
448 449
449#define SOLO_VD_CFG0 0x0900 450#define SOLO_VD_CFG0 0x0900
450#define SOLO6010_VD_CFG_NO_WRITE_NO_WINDOW (1<<24) /* 6010 only */ 451#define SOLO_VD_CFG_NO_WRITE_NO_WINDOW (1<<24)
451#define SOLO_VD_CFG_BUSY_WIAT_CODE (1<<23) 452#define SOLO_VD_CFG_BUSY_WIAT_CODE (1<<23)
452#define SOLO_VD_CFG_BUSY_WIAT_REF (1<<22) 453#define SOLO_VD_CFG_BUSY_WIAT_REF (1<<22)
453#define SOLO_VD_CFG_BUSY_WIAT_RES (1<<21) 454#define SOLO_VD_CFG_BUSY_WIAT_RES (1<<21)
@@ -599,9 +600,9 @@
599#define SOLO_UART_RX_DATA_POP (1<<8) 600#define SOLO_UART_RX_DATA_POP (1<<8)
600 601
601#define SOLO_TIMER_CLOCK_NUM 0x0be0 602#define SOLO_TIMER_CLOCK_NUM 0x0be0
602#define SOLO_TIMER_WATCHDOG 0x0be4
603#define SOLO_TIMER_USEC 0x0be8 603#define SOLO_TIMER_USEC 0x0be8
604#define SOLO_TIMER_SEC 0x0bec 604#define SOLO_TIMER_SEC 0x0bec
605#define SOLO_TIMER_USEC_LSB 0x0d20 /* 6110 Only */
605 606
606#define SOLO_AUDIO_CONTROL 0x0D00 607#define SOLO_AUDIO_CONTROL 0x0D00
607#define SOLO_AUDIO_ENABLE (1<<31) 608#define SOLO_AUDIO_ENABLE (1<<31)
@@ -629,9 +630,10 @@
629#define SOLO_AUDIO_EVOL(ch, value) ((value)<<((ch)%10)) 630#define SOLO_AUDIO_EVOL(ch, value) ((value)<<((ch)%10))
630#define SOLO_AUDIO_STA 0x0D14 631#define SOLO_AUDIO_STA 0x0D14
631 632
632 633/*
633#define SOLO_WATCHDOG 0x0BE4 634 * Watchdog configuration
634#define WATCHDOG_STAT(status) (status<<8) 635 */
635#define WATCHDOG_TIME(sec) (sec&0xff) 636#define SOLO_WATCHDOG 0x0be4
637#define SOLO_WATCHDOG_SET(status, sec) (status << 8 | (sec & 0xff))
636 638
637#endif /* __SOLO6X10_REGISTERS_H */ 639#endif /* __SOLO6X10_REGISTERS_H */
diff --git a/drivers/staging/media/solo6x10/solo6x10-jpeg.h b/drivers/staging/media/solo6x10/solo6x10-jpeg.h
index 50defec318cc..c5218ceeabca 100644
--- a/drivers/staging/media/solo6x10/solo6x10-jpeg.h
+++ b/drivers/staging/media/solo6x10/solo6x10-jpeg.h
@@ -1,6 +1,11 @@
1/* 1/*
2 * Copyright (C) 2010 Bluecherry, LLC www.bluecherrydvr.com 2 * Copyright (C) 2010-2013 Bluecherry, LLC <http://www.bluecherrydvr.com>
3 * Copyright (C) 2010 Ben Collins <bcollins@bluecherry.net> 3 *
4 * Original author:
5 * Ben Collins <bcollins@ubuntu.com>
6 *
7 * Additional work by:
8 * John Brooks <john.brooks@bluecherry.net>
4 * 9 *
5 * This program is free software; you can redistribute it and/or modify 10 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by 11 * it under the terms of the GNU General Public License as published by
@@ -20,7 +25,7 @@
20#ifndef __SOLO6X10_JPEG_H 25#ifndef __SOLO6X10_JPEG_H
21#define __SOLO6X10_JPEG_H 26#define __SOLO6X10_JPEG_H
22 27
23static unsigned char jpeg_header[] = { 28static const unsigned char jpeg_header[] = {
24 0xff, 0xd8, 0xff, 0xfe, 0x00, 0x0d, 0x42, 0x6c, 29 0xff, 0xd8, 0xff, 0xfe, 0x00, 0x0d, 0x42, 0x6c,
25 0x75, 0x65, 0x63, 0x68, 0x65, 0x72, 0x72, 0x79, 30 0x75, 0x65, 0x63, 0x68, 0x65, 0x72, 0x72, 0x79,
26 0x20, 0xff, 0xdb, 0x00, 0x43, 0x00, 0x20, 0x16, 31 0x20, 0xff, 0xdb, 0x00, 0x43, 0x00, 0x20, 0x16,
@@ -102,4 +107,87 @@ static unsigned char jpeg_header[] = {
102/* This is the byte marker for the start of SOF0: 0xffc0 marker */ 107/* This is the byte marker for the start of SOF0: 0xffc0 marker */
103#define SOF0_START 575 108#define SOF0_START 575
104 109
110/* This is the byte marker for the start of the DQT */
111#define DQT_START 17
112#define DQT_LEN 138
113const unsigned char jpeg_dqt[4][DQT_LEN] = {
114 {
115 0xff, 0xdb, 0x00, 0x43, 0x00,
116 0x08, 0x06, 0x06, 0x07, 0x06, 0x05, 0x08, 0x07,
117 0x07, 0x07, 0x09, 0x09, 0x08, 0x0a, 0x0c, 0x14,
118 0x0d, 0x0c, 0x0b, 0x0b, 0x0c, 0x19, 0x12, 0x13,
119 0x0f, 0x14, 0x1d, 0x1a, 0x1f, 0x1e, 0x1d, 0x1a,
120 0x1c, 0x1c, 0x20, 0x24, 0x2e, 0x27, 0x20, 0x22,
121 0x2c, 0x23, 0x1c, 0x1c, 0x28, 0x37, 0x29, 0x2c,
122 0x30, 0x31, 0x34, 0x34, 0x34, 0x1f, 0x27, 0x39,
123 0x3d, 0x38, 0x32, 0x3c, 0x2e, 0x33, 0x34, 0x32,
124 0xff, 0xdb, 0x00, 0x43, 0x01,
125 0x09, 0x09, 0x09, 0x0c, 0x0b, 0x0c, 0x18, 0x0d,
126 0x0d, 0x18, 0x32, 0x21, 0x1c, 0x21, 0x32, 0x32,
127 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32,
128 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32,
129 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32,
130 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32,
131 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32,
132 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32
133 }, {
134 0xff, 0xdb, 0x00, 0x43, 0x00,
135 0x10, 0x0b, 0x0c, 0x0e, 0x0c, 0x0a, 0x10, 0x0e,
136 0x0d, 0x0e, 0x12, 0x11, 0x10, 0x13, 0x18, 0x28,
137 0x1a, 0x18, 0x16, 0x16, 0x18, 0x31, 0x23, 0x25,
138 0x1d, 0x28, 0x3a, 0x33, 0x3d, 0x3c, 0x39, 0x33,
139 0x38, 0x37, 0x40, 0x48, 0x5c, 0x4e, 0x40, 0x44,
140 0x57, 0x45, 0x37, 0x38, 0x50, 0x6d, 0x51, 0x57,
141 0x5f, 0x62, 0x67, 0x68, 0x67, 0x3e, 0x4d, 0x71,
142 0x79, 0x70, 0x64, 0x78, 0x5c, 0x65, 0x67, 0x63,
143 0xff, 0xdb, 0x00, 0x43, 0x01,
144 0x11, 0x12, 0x12, 0x18, 0x15, 0x18, 0x2f, 0x1a,
145 0x1a, 0x2f, 0x63, 0x42, 0x38, 0x42, 0x63, 0x63,
146 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
147 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
148 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
149 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
150 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
151 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63
152 }, {
153 0xff, 0xdb, 0x00, 0x43, 0x00,
154 0x20, 0x16, 0x18, 0x1c, 0x18, 0x14, 0x20, 0x1c,
155 0x1a, 0x1c, 0x24, 0x22, 0x20, 0x26, 0x30, 0x50,
156 0x34, 0x30, 0x2c, 0x2c, 0x30, 0x62, 0x46, 0x4a,
157 0x3a, 0x50, 0x74, 0x66, 0x7a, 0x78, 0x72, 0x66,
158 0x70, 0x6e, 0x80, 0x90, 0xb8, 0x9c, 0x80, 0x88,
159 0xae, 0x8a, 0x6e, 0x70, 0xa0, 0xda, 0xa2, 0xae,
160 0xbe, 0xc4, 0xce, 0xd0, 0xce, 0x7c, 0x9a, 0xe2,
161 0xf2, 0xe0, 0xc8, 0xf0, 0xb8, 0xca, 0xce, 0xc6,
162 0xff, 0xdb, 0x00, 0x43, 0x01,
163 0x22, 0x24, 0x24, 0x30, 0x2a, 0x30, 0x5e, 0x34,
164 0x34, 0x5e, 0xc6, 0x84, 0x70, 0x84, 0xc6, 0xc6,
165 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6,
166 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6,
167 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6,
168 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6,
169 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6,
170 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6
171 }, {
172 0xff, 0xdb, 0x00, 0x43, 0x00,
173 0x30, 0x21, 0x24, 0x2a, 0x24, 0x1e, 0x30, 0x2a,
174 0x27, 0x2a, 0x36, 0x33, 0x30, 0x39, 0x48, 0x78,
175 0x4e, 0x48, 0x42, 0x42, 0x48, 0x93, 0x69, 0x6f,
176 0x57, 0x78, 0xae, 0x99, 0xb7, 0xb4, 0xab, 0x99,
177 0xa8, 0xa5, 0xc0, 0xd8, 0xff, 0xea, 0xc0, 0xcc,
178 0xff, 0xcf, 0xa5, 0xa8, 0xf0, 0xff, 0xf3, 0xff,
179 0xff, 0xff, 0xff, 0xff, 0xff, 0xba, 0xe7, 0xff,
180 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
181 0xff, 0xdb, 0x00, 0x43, 0x01,
182 0x33, 0x36, 0x36, 0x48, 0x3f, 0x48, 0x8d, 0x4e,
183 0x4e, 0x8d, 0xff, 0xc6, 0xa8, 0xc6, 0xff, 0xff,
184 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
185 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
186 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
187 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
188 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
189 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
190 }
191};
192
105#endif /* __SOLO6X10_JPEG_H */ 193#endif /* __SOLO6X10_JPEG_H */
diff --git a/drivers/staging/media/solo6x10/solo6x10.h b/drivers/staging/media/solo6x10/solo6x10.h
index abee7213202f..a75d9395b7b1 100644
--- a/drivers/staging/media/solo6x10/solo6x10.h
+++ b/drivers/staging/media/solo6x10/solo6x10.h
@@ -1,6 +1,11 @@
1/* 1/*
2 * Copyright (C) 2010 Bluecherry, LLC www.bluecherrydvr.com 2 * Copyright (C) 2010-2013 Bluecherry, LLC <http://www.bluecherrydvr.com>
3 * Copyright (C) 2010 Ben Collins <bcollins@bluecherry.net> 3 *
4 * Original author:
5 * Ben Collins <bcollins@ubuntu.com>
6 *
7 * Additional work by:
8 * John Brooks <john.brooks@bluecherry.net>
4 * 9 *
5 * This program is free software; you can redistribute it and/or modify 10 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by 11 * it under the terms of the GNU General Public License as published by
@@ -20,20 +25,20 @@
20#ifndef __SOLO6X10_H 25#ifndef __SOLO6X10_H
21#define __SOLO6X10_H 26#define __SOLO6X10_H
22 27
23#include <linux/version.h>
24#include <linux/pci.h> 28#include <linux/pci.h>
25#include <linux/i2c.h> 29#include <linux/i2c.h>
26#include <linux/semaphore.h>
27#include <linux/mutex.h> 30#include <linux/mutex.h>
28#include <linux/list.h> 31#include <linux/list.h>
29#include <linux/wait.h> 32#include <linux/wait.h>
30#include <linux/delay.h> 33#include <linux/stringify.h>
31#include <linux/slab.h> 34#include <linux/io.h>
32#include <asm/io.h>
33#include <linux/atomic.h> 35#include <linux/atomic.h>
36#include <linux/slab.h>
34#include <linux/videodev2.h> 37#include <linux/videodev2.h>
38
35#include <media/v4l2-dev.h> 39#include <media/v4l2-dev.h>
36#include <media/videobuf-core.h> 40#include <media/videobuf-core.h>
41
37#include "registers.h" 42#include "registers.h"
38 43
39#ifndef PCI_VENDOR_ID_SOFTLOGIC 44#ifndef PCI_VENDOR_ID_SOFTLOGIC
@@ -58,19 +63,24 @@
58#define PCI_DEVICE_ID_BC_6110_16 0x5310 63#define PCI_DEVICE_ID_BC_6110_16 0x5310
59#endif /* Bluecherry */ 64#endif /* Bluecherry */
60 65
66/* Used in pci_device_id, and solo_dev->type */
67#define SOLO_DEV_6010 0
68#define SOLO_DEV_6110 1
69
61#define SOLO6X10_NAME "solo6x10" 70#define SOLO6X10_NAME "solo6x10"
62 71
63#define SOLO_MAX_CHANNELS 16 72#define SOLO_MAX_CHANNELS 16
64 73
65/* Make sure these two match */ 74/* Make sure these two match */
66#define SOLO6X10_VERSION "2.1.0"
67#define SOLO6X10_VER_MAJOR 2 75#define SOLO6X10_VER_MAJOR 2
68#define SOLO6X10_VER_MINOR 0 76#define SOLO6X10_VER_MINOR 4
69#define SOLO6X10_VER_SUB 0 77#define SOLO6X10_VER_SUB 4
70#define SOLO6X10_VER_NUM \ 78#define SOLO6X10_VER_NUM \
71 KERNEL_VERSION(SOLO6X10_VER_MAJOR, SOLO6X10_VER_MINOR, SOLO6X10_VER_SUB) 79 KERNEL_VERSION(SOLO6X10_VER_MAJOR, SOLO6X10_VER_MINOR, SOLO6X10_VER_SUB)
72 80#define SOLO6X10_VERSION \
73#define FLAGS_6110 1 81 __stringify(SOLO6X10_VER_MAJOR) "." \
82 __stringify(SOLO6X10_VER_MINOR) "." \
83 __stringify(SOLO6X10_VER_SUB)
74 84
75/* 85/*
76 * The SOLO6x10 actually has 8 i2c channels, but we only use 2. 86 * The SOLO6x10 actually has 8 i2c channels, but we only use 2.
@@ -84,16 +94,7 @@
84/* DMA Engine setup */ 94/* DMA Engine setup */
85#define SOLO_NR_P2M 4 95#define SOLO_NR_P2M 4
86#define SOLO_NR_P2M_DESC 256 96#define SOLO_NR_P2M_DESC 256
87/* MPEG and JPEG share the same interrupt and locks so they must be together 97#define SOLO_P2M_DESC_SIZE (SOLO_NR_P2M_DESC * 16)
88 * in the same dma channel. */
89#define SOLO_P2M_DMA_ID_MP4E 0
90#define SOLO_P2M_DMA_ID_JPEG 0
91#define SOLO_P2M_DMA_ID_MP4D 1
92#define SOLO_P2M_DMA_ID_G723D 1
93#define SOLO_P2M_DMA_ID_DISP 2
94#define SOLO_P2M_DMA_ID_OSG 2
95#define SOLO_P2M_DMA_ID_G723E 3
96#define SOLO_P2M_DMA_ID_VIN 3
97 98
98/* Encoder standard modes */ 99/* Encoder standard modes */
99#define SOLO_ENC_MODE_CIF 2 100#define SOLO_ENC_MODE_CIF 2
@@ -103,12 +104,6 @@
103#define SOLO_DEFAULT_GOP 30 104#define SOLO_DEFAULT_GOP 30
104#define SOLO_DEFAULT_QP 3 105#define SOLO_DEFAULT_QP 3
105 106
106/* There is 8MB memory available for solo to buffer MPEG4 frames.
107 * This gives us 512 * 16kbyte queues. */
108#define SOLO_NR_RING_BUFS 512
109
110#define SOLO_CLOCK_MHZ 108
111
112#ifndef V4L2_BUF_FLAG_MOTION_ON 107#ifndef V4L2_BUF_FLAG_MOTION_ON
113#define V4L2_BUF_FLAG_MOTION_ON 0x0400 108#define V4L2_BUF_FLAG_MOTION_ON 0x0400
114#define V4L2_BUF_FLAG_MOTION_DETECTED 0x0800 109#define V4L2_BUF_FLAG_MOTION_DETECTED 0x0800
@@ -128,64 +123,67 @@ enum SOLO_I2C_STATE {
128 IIC_STATE_STOP 123 IIC_STATE_STOP
129}; 124};
130 125
131struct p2m_desc { 126/* Defined in Table 4-16, Page 68-69 of the 6010 Datasheet */
132 u32 ctrl; 127struct solo_p2m_desc {
133 u32 ext; 128 u32 ctrl;
134 u32 ta; 129 u32 cfg;
135 u32 fa; 130 u32 dma_addr;
131 u32 ext_addr;
136}; 132};
137 133
138struct solo_p2m_dev { 134struct solo_p2m_dev {
139 struct mutex mutex; 135 struct mutex mutex;
140 struct completion completion; 136 struct completion completion;
137 int desc_count;
138 int desc_idx;
139 struct solo_p2m_desc *descs;
141 int error; 140 int error;
142}; 141};
143 142
144#define OSD_TEXT_MAX 30 143#define OSD_TEXT_MAX 44
145
146enum solo_enc_types {
147 SOLO_ENC_TYPE_STD,
148 SOLO_ENC_TYPE_EXT,
149};
150 144
151struct solo_enc_dev { 145struct solo_enc_dev {
152 struct solo_dev *solo_dev; 146 struct solo_dev *solo_dev;
153 /* V4L2 Items */ 147 /* V4L2 Items */
154 struct video_device *vfd; 148 struct video_device *vfd;
155 /* General accounting */ 149 /* General accounting */
156 wait_queue_head_t thread_wait; 150 struct mutex enable_lock;
157 spinlock_t lock; 151 spinlock_t motion_lock;
158 atomic_t readers; 152 atomic_t readers;
153 atomic_t mpeg_readers;
159 u8 ch; 154 u8 ch;
160 u8 mode, gop, qp, interlaced, interval; 155 u8 mode, gop, qp, interlaced, interval;
161 u8 reset_gop;
162 u8 bw_weight; 156 u8 bw_weight;
163 u8 motion_detected;
164 u16 motion_thresh; 157 u16 motion_thresh;
165 u16 width; 158 u16 width;
166 u16 height; 159 u16 height;
160
161 /* OSD buffers */
167 char osd_text[OSD_TEXT_MAX + 1]; 162 char osd_text[OSD_TEXT_MAX + 1];
168}; 163 u8 osd_buf[SOLO_EOSD_EXT_SIZE_MAX]
164 __aligned(4);
169 165
170struct solo_enc_buf { 166 /* VOP stuff */
171 u8 vop; 167 unsigned char vop[64];
172 u8 ch; 168 int vop_len;
173 enum solo_enc_types type; 169 unsigned char jpeg_header[1024];
174 u32 off; 170 int jpeg_len;
175 u32 size; 171
176 u32 jpeg_off; 172 /* File handles that are listening for buffers */
177 u32 jpeg_size; 173 struct list_head listeners;
178 struct timeval ts;
179}; 174};
180 175
181/* The SOLO6x10 PCI Device */ 176/* The SOLO6x10 PCI Device */
182struct solo_dev { 177struct solo_dev {
183 /* General stuff */ 178 /* General stuff */
184 struct pci_dev *pdev; 179 struct pci_dev *pdev;
180 int type;
181 unsigned int time_sync;
182 unsigned int usec_lsb;
183 unsigned int clock_mhz;
185 u8 __iomem *reg_base; 184 u8 __iomem *reg_base;
186 int nr_chans; 185 int nr_chans;
187 int nr_ext; 186 int nr_ext;
188 u32 flags;
189 u32 irq_mask; 187 u32 irq_mask;
190 u32 motion_mask; 188 u32 motion_mask;
191 spinlock_t reg_io_lock; 189 spinlock_t reg_io_lock;
@@ -206,6 +204,9 @@ struct solo_dev {
206 204
207 /* P2M DMA Engine */ 205 /* P2M DMA Engine */
208 struct solo_p2m_dev p2m_dev[SOLO_NR_P2M]; 206 struct solo_p2m_dev p2m_dev[SOLO_NR_P2M];
207 atomic_t p2m_count;
208 int p2m_jiffies;
209 unsigned int p2m_timeouts;
209 210
210 /* V4L2 Display items */ 211 /* V4L2 Display items */
211 struct video_device *vfd; 212 struct video_device *vfd;
@@ -219,9 +220,6 @@ struct solo_dev {
219 u16 enc_bw_remain; 220 u16 enc_bw_remain;
220 /* IDX into hw mp4 encoder */ 221 /* IDX into hw mp4 encoder */
221 u8 enc_idx; 222 u8 enc_idx;
222 /* Our software ring of enc buf references */
223 u16 enc_wr_idx;
224 struct solo_enc_buf enc_buf[SOLO_NR_RING_BUFS];
225 223
226 /* Current video settings */ 224 /* Current video settings */
227 u32 video_type; 225 u32 video_type;
@@ -230,11 +228,32 @@ struct solo_dev {
230 u16 vin_hstart, vin_vstart; 228 u16 vin_hstart, vin_vstart;
231 u8 fps; 229 u8 fps;
232 230
231 /* JPEG Qp setting */
232 spinlock_t jpeg_qp_lock;
233 u32 jpeg_qp[2];
234
233 /* Audio components */ 235 /* Audio components */
234 struct snd_card *snd_card; 236 struct snd_card *snd_card;
235 struct snd_pcm *snd_pcm; 237 struct snd_pcm *snd_pcm;
236 atomic_t snd_users; 238 atomic_t snd_users;
237 int g723_hw_idx; 239 int g723_hw_idx;
240
241 /* sysfs stuffs */
242 struct device dev;
243 int sdram_size;
244 struct bin_attribute sdram_attr;
245 unsigned int sys_config;
246
247 /* Ring thread */
248 struct task_struct *ring_thread;
249 wait_queue_head_t ring_thread_wait;
250 atomic_t enc_users;
251 atomic_t disp_users;
252
253 /* VOP_HEADER handling */
254 void *vh_buf;
255 dma_addr_t vh_dma;
256 int vh_size;
238}; 257};
239 258
240static inline u32 solo_reg_read(struct solo_dev *solo_dev, int reg) 259static inline u32 solo_reg_read(struct solo_dev *solo_dev, int reg)
@@ -255,7 +274,8 @@ static inline u32 solo_reg_read(struct solo_dev *solo_dev, int reg)
255 return ret; 274 return ret;
256} 275}
257 276
258static inline void solo_reg_write(struct solo_dev *solo_dev, int reg, u32 data) 277static inline void solo_reg_write(struct solo_dev *solo_dev, int reg,
278 u32 data)
259{ 279{
260 unsigned long flags; 280 unsigned long flags;
261 u16 val; 281 u16 val;
@@ -270,8 +290,17 @@ static inline void solo_reg_write(struct solo_dev *solo_dev, int reg, u32 data)
270 spin_unlock_irqrestore(&solo_dev->reg_io_lock, flags); 290 spin_unlock_irqrestore(&solo_dev->reg_io_lock, flags);
271} 291}
272 292
273void solo_irq_on(struct solo_dev *solo_dev, u32 mask); 293static inline void solo_irq_on(struct solo_dev *dev, u32 mask)
274void solo_irq_off(struct solo_dev *solo_dev, u32 mask); 294{
295 dev->irq_mask |= mask;
296 solo_reg_write(dev, SOLO_IRQ_MASK, dev->irq_mask);
297}
298
299static inline void solo_irq_off(struct solo_dev *dev, u32 mask)
300{
301 dev->irq_mask &= ~mask;
302 solo_reg_write(dev, SOLO_IRQ_MASK, dev->irq_mask);
303}
275 304
276/* Init/exit routeines for subsystems */ 305/* Init/exit routeines for subsystems */
277int solo_disp_init(struct solo_dev *solo_dev); 306int solo_disp_init(struct solo_dev *solo_dev);
@@ -286,13 +315,13 @@ void solo_i2c_exit(struct solo_dev *solo_dev);
286int solo_p2m_init(struct solo_dev *solo_dev); 315int solo_p2m_init(struct solo_dev *solo_dev);
287void solo_p2m_exit(struct solo_dev *solo_dev); 316void solo_p2m_exit(struct solo_dev *solo_dev);
288 317
289int solo_v4l2_init(struct solo_dev *solo_dev); 318int solo_v4l2_init(struct solo_dev *solo_dev, unsigned nr);
290void solo_v4l2_exit(struct solo_dev *solo_dev); 319void solo_v4l2_exit(struct solo_dev *solo_dev);
291 320
292int solo_enc_init(struct solo_dev *solo_dev); 321int solo_enc_init(struct solo_dev *solo_dev);
293void solo_enc_exit(struct solo_dev *solo_dev); 322void solo_enc_exit(struct solo_dev *solo_dev);
294 323
295int solo_enc_v4l2_init(struct solo_dev *solo_dev); 324int solo_enc_v4l2_init(struct solo_dev *solo_dev, unsigned nr);
296void solo_enc_v4l2_exit(struct solo_dev *solo_dev); 325void solo_enc_v4l2_exit(struct solo_dev *solo_dev);
297 326
298int solo_g723_init(struct solo_dev *solo_dev); 327int solo_g723_init(struct solo_dev *solo_dev);
@@ -301,7 +330,7 @@ void solo_g723_exit(struct solo_dev *solo_dev);
301/* ISR's */ 330/* ISR's */
302int solo_i2c_isr(struct solo_dev *solo_dev); 331int solo_i2c_isr(struct solo_dev *solo_dev);
303void solo_p2m_isr(struct solo_dev *solo_dev, int id); 332void solo_p2m_isr(struct solo_dev *solo_dev, int id);
304void solo_p2m_error_isr(struct solo_dev *solo_dev, u32 status); 333void solo_p2m_error_isr(struct solo_dev *solo_dev);
305void solo_enc_v4l2_isr(struct solo_dev *solo_dev); 334void solo_enc_v4l2_isr(struct solo_dev *solo_dev);
306void solo_g723_isr(struct solo_dev *solo_dev); 335void solo_g723_isr(struct solo_dev *solo_dev);
307void solo_motion_isr(struct solo_dev *solo_dev); 336void solo_motion_isr(struct solo_dev *solo_dev);
@@ -313,24 +342,39 @@ void solo_i2c_writebyte(struct solo_dev *solo_dev, int id, u8 addr, u8 off,
313 u8 data); 342 u8 data);
314 343
315/* P2M DMA */ 344/* P2M DMA */
316int solo_p2m_dma_t(struct solo_dev *solo_dev, u8 id, int wr, 345int solo_p2m_dma_t(struct solo_dev *solo_dev, int wr,
317 dma_addr_t dma_addr, u32 ext_addr, u32 size); 346 dma_addr_t dma_addr, u32 ext_addr, u32 size,
318int solo_p2m_dma(struct solo_dev *solo_dev, u8 id, int wr, 347 int repeat, u32 ext_size);
319 void *sys_addr, u32 ext_addr, u32 size); 348int solo_p2m_dma(struct solo_dev *solo_dev, int wr,
320int solo_p2m_dma_sg(struct solo_dev *solo_dev, u8 id, 349 void *sys_addr, u32 ext_addr, u32 size,
321 struct p2m_desc *pdesc, int wr, 350 int repeat, u32 ext_size);
322 struct scatterlist *sglist, u32 sg_off, 351void solo_p2m_fill_desc(struct solo_p2m_desc *desc, int wr,
323 u32 ext_addr, u32 size); 352 dma_addr_t dma_addr, u32 ext_addr, u32 size,
324void solo_p2m_push_desc(struct p2m_desc *desc, int wr, dma_addr_t dma_addr, 353 int repeat, u32 ext_size);
325 u32 ext_addr, u32 size, int repeat, u32 ext_size); 354int solo_p2m_dma_desc(struct solo_dev *solo_dev,
326int solo_p2m_dma_desc(struct solo_dev *solo_dev, u8 id, 355 struct solo_p2m_desc *desc, dma_addr_t desc_dma,
327 struct p2m_desc *desc, int desc_count); 356 int desc_cnt);
328 357
329/* Set the threshold for motion detection */ 358/* Set the threshold for motion detection */
330void solo_set_motion_threshold(struct solo_dev *solo_dev, u8 ch, u16 val); 359int solo_set_motion_threshold(struct solo_dev *solo_dev, u8 ch, u16 val);
360int solo_set_motion_block(struct solo_dev *solo_dev, u8 ch, u16 val,
361 u16 block);
331#define SOLO_DEF_MOT_THRESH 0x0300 362#define SOLO_DEF_MOT_THRESH 0x0300
332 363
333/* Write text on OSD */ 364/* Write text on OSD */
334int solo_osd_print(struct solo_enc_dev *solo_enc); 365int solo_osd_print(struct solo_enc_dev *solo_enc);
335 366
367/* EEPROM commands */
368unsigned int solo_eeprom_ewen(struct solo_dev *solo_dev, int w_en);
369unsigned short solo_eeprom_read(struct solo_dev *solo_dev, int loc);
370int solo_eeprom_write(struct solo_dev *solo_dev, int loc,
371 unsigned short data);
372
373/* JPEG Qp functions */
374void solo_s_jpeg_qp(struct solo_dev *solo_dev, unsigned int ch,
375 unsigned int qp);
376int solo_g_jpeg_qp(struct solo_dev *solo_dev, unsigned int ch);
377
378#define CHK_FLAGS(v, flags) (((v) & (flags)) == (flags))
379
336#endif /* __SOLO6X10_H */ 380#endif /* __SOLO6X10_H */
diff --git a/drivers/staging/media/solo6x10/tw28.c b/drivers/staging/media/solo6x10/tw28.c
index db56b42c56c6..365ab1012881 100644
--- a/drivers/staging/media/solo6x10/tw28.c
+++ b/drivers/staging/media/solo6x10/tw28.c
@@ -1,6 +1,11 @@
1/* 1/*
2 * Copyright (C) 2010 Bluecherry, LLC www.bluecherrydvr.com 2 * Copyright (C) 2010-2013 Bluecherry, LLC <http://www.bluecherrydvr.com>
3 * Copyright (C) 2010 Ben Collins <bcollins@bluecherry.net> 3 *
4 * Original author:
5 * Ben Collins <bcollins@ubuntu.com>
6 *
7 * Additional work by:
8 * John Brooks <john.brooks@bluecherry.net>
4 * 9 *
5 * This program is free software; you can redistribute it and/or modify 10 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by 11 * it under the terms of the GNU General Public License as published by
@@ -18,12 +23,12 @@
18 */ 23 */
19 24
20#include <linux/kernel.h> 25#include <linux/kernel.h>
26#include <linux/delay.h>
27
21#include "solo6x10.h" 28#include "solo6x10.h"
22#include "tw28.h" 29#include "tw28.h"
23 30
24/* XXX: Some of these values are masked into an 8-bit regs, and shifted 31#define DEFAULT_HDELAY_NTSC (32 - 8)
25 * around for other 8-bit regs. What are the magic bits in these values? */
26#define DEFAULT_HDELAY_NTSC (32 - 4)
27#define DEFAULT_HACTIVE_NTSC (720 + 16) 32#define DEFAULT_HACTIVE_NTSC (720 + 16)
28#define DEFAULT_VDELAY_NTSC (7 - 2) 33#define DEFAULT_VDELAY_NTSC (7 - 2)
29#define DEFAULT_VACTIVE_NTSC (240 + 4) 34#define DEFAULT_VACTIVE_NTSC (240 + 4)
@@ -33,15 +38,16 @@
33#define DEFAULT_VDELAY_PAL (6) 38#define DEFAULT_VDELAY_PAL (6)
34#define DEFAULT_VACTIVE_PAL (312-DEFAULT_VDELAY_PAL) 39#define DEFAULT_VACTIVE_PAL (312-DEFAULT_VDELAY_PAL)
35 40
36static u8 tbl_tw2864_template[] = { 41
37 0x00, 0x00, 0x80, 0x10, 0x80, 0x80, 0x00, 0x02, /* 0x00 */ 42static const u8 tbl_tw2864_ntsc_template[] = {
38 0x12, 0xf5, 0x09, 0xd0, 0x00, 0x00, 0x00, 0x7f, 43 0x00, 0xf0, 0x70, 0x30, 0x80, 0x80, 0x00, 0x02, /* 0x00 */
39 0x00, 0x00, 0x80, 0x10, 0x80, 0x80, 0x00, 0x02, /* 0x10 */ 44 0x12, 0xf5, 0x0c, 0xd0, 0x00, 0x00, 0x00, 0x7f,
40 0x12, 0xf5, 0x09, 0xd0, 0x00, 0x00, 0x00, 0x7f, 45 0x00, 0xf0, 0x70, 0x30, 0x80, 0x80, 0x00, 0x02, /* 0x10 */
41 0x00, 0x00, 0x80, 0x10, 0x80, 0x80, 0x00, 0x02, /* 0x20 */ 46 0x12, 0xf5, 0x0c, 0xd0, 0x00, 0x00, 0x00, 0x7f,
42 0x12, 0xf5, 0x09, 0xd0, 0x00, 0x00, 0x00, 0x7f, 47 0x00, 0xf0, 0x70, 0x30, 0x80, 0x80, 0x00, 0x02, /* 0x20 */
43 0x00, 0x00, 0x80, 0x10, 0x80, 0x80, 0x00, 0x02, /* 0x30 */ 48 0x12, 0xf5, 0x0c, 0xd0, 0x00, 0x00, 0x00, 0x7f,
44 0x12, 0xf5, 0x09, 0xd0, 0x00, 0x00, 0x00, 0x7f, 49 0x00, 0xf0, 0x70, 0x30, 0x80, 0x80, 0x00, 0x02, /* 0x30 */
50 0x12, 0xf5, 0x0c, 0xd0, 0x00, 0x00, 0x00, 0x7f,
45 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x40 */ 51 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x40 */
46 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 52 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
47 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x50 */ 53 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x50 */
@@ -61,14 +67,49 @@ static u8 tbl_tw2864_template[] = {
61 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc0 */ 67 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc0 */
62 0x00, 0x00, 0x55, 0x00, 0xb1, 0xe4, 0x40, 0x00, 68 0x00, 0x00, 0x55, 0x00, 0xb1, 0xe4, 0x40, 0x00,
63 0x77, 0x77, 0x01, 0x13, 0x57, 0x9b, 0xdf, 0x20, /* 0xd0 */ 69 0x77, 0x77, 0x01, 0x13, 0x57, 0x9b, 0xdf, 0x20, /* 0xd0 */
64 0x64, 0xa8, 0xec, 0xd1, 0x0f, 0x11, 0x11, 0x81, 70 0x64, 0xa8, 0xec, 0xc1, 0x0f, 0x11, 0x11, 0x81,
65 0x10, 0xe0, 0xbb, 0xbb, 0x00, 0x11, 0x00, 0x00, /* 0xe0 */ 71 0x00, 0xe0, 0xbb, 0xbb, 0x00, 0x11, 0x00, 0x00, /* 0xe0 */
66 0x11, 0x00, 0x00, 0x11, 0x00, 0x00, 0x11, 0x00, 72 0x11, 0x00, 0x00, 0x11, 0x00, 0x00, 0x11, 0x00,
67 0x83, 0xb5, 0x09, 0x78, 0x85, 0x00, 0x01, 0x20, /* 0xf0 */ 73 0x83, 0xb5, 0x09, 0x78, 0x85, 0x00, 0x01, 0x20, /* 0xf0 */
68 0x64, 0x11, 0x40, 0xaf, 0xff, 0x00, 0x00, 0x00, 74 0x64, 0x11, 0x40, 0xaf, 0xff, 0x00, 0x00, 0x00,
69}; 75};
70 76
71static u8 tbl_tw2865_ntsc_template[] = { 77static const u8 tbl_tw2864_pal_template[] = {
78 0x00, 0xf0, 0x70, 0x30, 0x80, 0x80, 0x00, 0x12, /* 0x00 */
79 0x18, 0xf5, 0x0c, 0xd0, 0x00, 0x00, 0x01, 0x7f,
80 0x00, 0xf0, 0x70, 0x30, 0x80, 0x80, 0x00, 0x12, /* 0x10 */
81 0x18, 0xf5, 0x0c, 0xd0, 0x00, 0x00, 0x01, 0x7f,
82 0x00, 0xf0, 0x70, 0x30, 0x80, 0x80, 0x00, 0x12, /* 0x20 */
83 0x18, 0xf5, 0x0c, 0xd0, 0x00, 0x00, 0x01, 0x7f,
84 0x00, 0xf0, 0x70, 0x30, 0x80, 0x80, 0x00, 0x12, /* 0x30 */
85 0x18, 0xf5, 0x0c, 0xd0, 0x00, 0x00, 0x01, 0x7f,
86 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x40 */
87 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
88 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x50 */
89 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
90 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x60 */
91 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
92 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70 */
93 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA3, 0x00,
94 0x00, 0x02, 0x00, 0xcc, 0x00, 0x80, 0x44, 0x50, /* 0x80 */
95 0x22, 0x01, 0xd8, 0xbc, 0xb8, 0x44, 0x38, 0x00,
96 0x00, 0x78, 0x72, 0x3e, 0x14, 0xa5, 0xe4, 0x05, /* 0x90 */
97 0x00, 0x28, 0x44, 0x44, 0xa0, 0x90, 0x5a, 0x01,
98 0x0a, 0x0a, 0x0a, 0x0a, 0x1a, 0x1a, 0x1a, 0x1a, /* 0xa0 */
99 0x00, 0x00, 0x00, 0xf0, 0xf0, 0xf0, 0xf0, 0x44,
100 0x44, 0x0a, 0x00, 0xff, 0xef, 0xef, 0xef, 0xef, /* 0xb0 */
101 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
102 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc0 */
103 0x00, 0x00, 0x55, 0x00, 0xb1, 0xe4, 0x40, 0x00,
104 0x77, 0x77, 0x01, 0x13, 0x57, 0x9b, 0xdf, 0x20, /* 0xd0 */
105 0x64, 0xa8, 0xec, 0xc1, 0x0f, 0x11, 0x11, 0x81,
106 0x00, 0xe0, 0xbb, 0xbb, 0x00, 0x11, 0x00, 0x00, /* 0xe0 */
107 0x11, 0x00, 0x00, 0x11, 0x00, 0x00, 0x11, 0x00,
108 0x83, 0xb5, 0x09, 0x00, 0xa0, 0x00, 0x01, 0x20, /* 0xf0 */
109 0x64, 0x11, 0x40, 0xaf, 0xff, 0x00, 0x00, 0x00,
110};
111
112static const u8 tbl_tw2865_ntsc_template[] = {
72 0x00, 0xf0, 0x70, 0x30, 0x80, 0x80, 0x00, 0x02, /* 0x00 */ 113 0x00, 0xf0, 0x70, 0x30, 0x80, 0x80, 0x00, 0x02, /* 0x00 */
73 0x12, 0xff, 0x09, 0xd0, 0x00, 0x00, 0x00, 0x7f, 114 0x12, 0xff, 0x09, 0xd0, 0x00, 0x00, 0x00, 0x7f,
74 0x00, 0xf0, 0x70, 0x30, 0x80, 0x80, 0x00, 0x02, /* 0x10 */ 115 0x00, 0xf0, 0x70, 0x30, 0x80, 0x80, 0x00, 0x02, /* 0x10 */
@@ -103,7 +144,7 @@ static u8 tbl_tw2865_ntsc_template[] = {
103 0x64, 0x51, 0x40, 0xaf, 0xFF, 0xF0, 0x00, 0xC0, 144 0x64, 0x51, 0x40, 0xaf, 0xFF, 0xF0, 0x00, 0xC0,
104}; 145};
105 146
106static u8 tbl_tw2865_pal_template[] = { 147static const u8 tbl_tw2865_pal_template[] = {
107 0x00, 0xf0, 0x70, 0x30, 0x80, 0x80, 0x00, 0x12, /* 0x00 */ 148 0x00, 0xf0, 0x70, 0x30, 0x80, 0x80, 0x00, 0x12, /* 0x00 */
108 0x11, 0xff, 0x01, 0xc3, 0x00, 0x00, 0x01, 0x7f, 149 0x11, 0xff, 0x01, 0xc3, 0x00, 0x00, 0x01, 0x7f,
109 0x00, 0xf0, 0x70, 0x30, 0x80, 0x80, 0x00, 0x12, /* 0x10 */ 150 0x00, 0xf0, 0x70, 0x30, 0x80, 0x80, 0x00, 0x12, /* 0x10 */
@@ -180,8 +221,8 @@ static void tw_write_and_verify(struct solo_dev *solo_dev, u8 addr, u8 off,
180 msleep_interruptible(1); 221 msleep_interruptible(1);
181 } 222 }
182 223
183/* printk("solo6x10/tw28: Error writing register: %02x->%02x [%02x]\n", 224/* printk("solo6x10/tw28: Error writing register: %02x->%02x [%02x]\n", */
184 addr, off, val); */ 225/* addr, off, val); */
185} 226}
186 227
187static int tw2865_setup(struct solo_dev *solo_dev, u8 dev_addr) 228static int tw2865_setup(struct solo_dev *solo_dev, u8 dev_addr)
@@ -216,16 +257,17 @@ static int tw2865_setup(struct solo_dev *solo_dev, u8 dev_addr)
216 257
217 for (i = 0; i < 0xff; i++) { 258 for (i = 0; i < 0xff; i++) {
218 /* Skip read only registers */ 259 /* Skip read only registers */
219 if (i >= 0xb8 && i <= 0xc1) 260 switch (i) {
220 continue; 261 case 0xb8 ... 0xc1:
221 if ((i & ~0x30) == 0x00 || 262 case 0xc4 ... 0xc7:
222 (i & ~0x30) == 0x0c || 263 case 0xfd:
223 (i & ~0x30) == 0x0d)
224 continue;
225 if (i >= 0xc4 && i <= 0xc7)
226 continue; 264 continue;
227 if (i == 0xfd) 265 }
266 switch (i & ~0x30) {
267 case 0x00:
268 case 0x0c ... 0x0d:
228 continue; 269 continue;
270 }
229 271
230 tw_write_and_verify(solo_dev, dev_addr, i, 272 tw_write_and_verify(solo_dev, dev_addr, i,
231 tbl_tw2865_common[i]); 273 tbl_tw2865_common[i]);
@@ -236,11 +278,15 @@ static int tw2865_setup(struct solo_dev *solo_dev, u8 dev_addr)
236 278
237static int tw2864_setup(struct solo_dev *solo_dev, u8 dev_addr) 279static int tw2864_setup(struct solo_dev *solo_dev, u8 dev_addr)
238{ 280{
239 u8 tbl_tw2864_common[sizeof(tbl_tw2864_template)]; 281 u8 tbl_tw2864_common[256];
240 int i; 282 int i;
241 283
242 memcpy(tbl_tw2864_common, tbl_tw2864_template, 284 if (solo_dev->video_type == SOLO_VO_FMT_TYPE_PAL)
243 sizeof(tbl_tw2864_common)); 285 memcpy(tbl_tw2864_common, tbl_tw2864_pal_template,
286 sizeof(tbl_tw2864_common));
287 else
288 memcpy(tbl_tw2864_common, tbl_tw2864_ntsc_template,
289 sizeof(tbl_tw2864_common));
244 290
245 if (solo_dev->tw2865 == 0) { 291 if (solo_dev->tw2865 == 0) {
246 /* IRQ Mode */ 292 /* IRQ Mode */
@@ -285,33 +331,19 @@ static int tw2864_setup(struct solo_dev *solo_dev, u8 dev_addr)
285 } 331 }
286 } 332 }
287 333
288 /* NTSC or PAL */
289 if (solo_dev->video_type == SOLO_VO_FMT_TYPE_PAL) {
290 for (i = 0; i < 4; i++) {
291 tbl_tw2864_common[0x07 | (i << 4)] |= 0x10;
292 tbl_tw2864_common[0x08 | (i << 4)] |= 0x06;
293 tbl_tw2864_common[0x0a | (i << 4)] |= 0x08;
294 tbl_tw2864_common[0x0b | (i << 4)] |= 0x13;
295 tbl_tw2864_common[0x0e | (i << 4)] |= 0x01;
296 }
297 tbl_tw2864_common[0x9d] = 0x90;
298 tbl_tw2864_common[0xf3] = 0x00;
299 tbl_tw2864_common[0xf4] = 0xa0;
300 }
301
302 for (i = 0; i < 0xff; i++) { 334 for (i = 0; i < 0xff; i++) {
303 /* Skip read only registers */ 335 /* Skip read only registers */
304 if (i >= 0xb8 && i <= 0xc1) 336 switch (i) {
305 continue; 337 case 0xb8 ... 0xc1:
306 if ((i & ~0x30) == 0x00 || 338 case 0xfd:
307 (i & ~0x30) == 0x0c ||
308 (i & ~0x30) == 0x0d)
309 continue;
310 if (i == 0x74 || i == 0x77 || i == 0x78 ||
311 i == 0x79 || i == 0x7a)
312 continue; 339 continue;
313 if (i == 0xfd) 340 }
341 switch (i & ~0x30) {
342 case 0x00:
343 case 0x0c:
344 case 0x0d:
314 continue; 345 continue;
346 }
315 347
316 tw_write_and_verify(solo_dev, dev_addr, i, 348 tw_write_and_verify(solo_dev, dev_addr, i,
317 tbl_tw2864_common[i]); 349 tbl_tw2864_common[i]);
@@ -544,8 +576,8 @@ int solo_tw28_init(struct solo_dev *solo_dev)
544 int i; 576 int i;
545 u8 value; 577 u8 value;
546 578
547 /* Detect techwell chip type */ 579 /* Detect techwell chip type(s) */
548 for (i = 0; i < TW_NUM_CHIP; i++) { 580 for (i = 0; i < solo_dev->nr_chans / 4; i++) {
549 value = solo_i2c_readbyte(solo_dev, SOLO_I2C_TW, 581 value = solo_i2c_readbyte(solo_dev, SOLO_I2C_TW,
550 TW_CHIP_OFFSET_ADDR(i), 0xFF); 582 TW_CHIP_OFFSET_ADDR(i), 0xFF);
551 583
@@ -560,7 +592,8 @@ int solo_tw28_init(struct solo_dev *solo_dev)
560 break; 592 break;
561 default: 593 default:
562 value = solo_i2c_readbyte(solo_dev, SOLO_I2C_TW, 594 value = solo_i2c_readbyte(solo_dev, SOLO_I2C_TW,
563 TW_CHIP_OFFSET_ADDR(i), 0x59); 595 TW_CHIP_OFFSET_ADDR(i),
596 0x59);
564 if ((value >> 3) == 0x04) { 597 if ((value >> 3) == 0x04) {
565 solo_dev->tw2815 |= 1 << i; 598 solo_dev->tw2815 |= 1 << i;
566 solo_dev->tw28_cnt++; 599 solo_dev->tw28_cnt++;
@@ -568,8 +601,11 @@ int solo_tw28_init(struct solo_dev *solo_dev)
568 } 601 }
569 } 602 }
570 603
571 if (!solo_dev->tw28_cnt) 604 if (solo_dev->tw28_cnt != (solo_dev->nr_chans >> 2)) {
605 dev_err(&solo_dev->pdev->dev,
606 "Could not initialize any techwell chips\n");
572 return -EINVAL; 607 return -EINVAL;
608 }
573 609
574 saa7128_setup(solo_dev); 610 saa7128_setup(solo_dev);
575 611
@@ -582,17 +618,6 @@ int solo_tw28_init(struct solo_dev *solo_dev)
582 tw2815_setup(solo_dev, TW_CHIP_OFFSET_ADDR(i)); 618 tw2815_setup(solo_dev, TW_CHIP_OFFSET_ADDR(i));
583 } 619 }
584 620
585 dev_info(&solo_dev->pdev->dev, "Initialized %d tw28xx chip%s:",
586 solo_dev->tw28_cnt, solo_dev->tw28_cnt == 1 ? "" : "s");
587
588 if (solo_dev->tw2865)
589 printk(" tw2865[%d]", hweight32(solo_dev->tw2865));
590 if (solo_dev->tw2864)
591 printk(" tw2864[%d]", hweight32(solo_dev->tw2864));
592 if (solo_dev->tw2815)
593 printk(" tw2815[%d]", hweight32(solo_dev->tw2815));
594 printk("\n");
595
596 return 0; 621 return 0;
597} 622}
598 623
@@ -610,7 +635,7 @@ int tw28_get_video_status(struct solo_dev *solo_dev, u8 ch)
610 chip_num = ch / 4; 635 chip_num = ch / 4;
611 ch %= 4; 636 ch %= 4;
612 637
613 val = tw_readbyte(solo_dev, chip_num, TW286X_AV_STAT_ADDR, 638 val = tw_readbyte(solo_dev, chip_num, TW286x_AV_STAT_ADDR,
614 TW_AV_STAT_ADDR) & 0x0f; 639 TW_AV_STAT_ADDR) & 0x0f;
615 640
616 return val & (1 << ch) ? 1 : 0; 641 return val & (1 << ch) ? 1 : 0;
@@ -626,7 +651,7 @@ u16 tw28_get_audio_status(struct solo_dev *solo_dev)
626 int i; 651 int i;
627 652
628 for (i = 0; i < solo_dev->tw28_cnt; i++) { 653 for (i = 0; i < solo_dev->tw28_cnt; i++) {
629 val = (tw_readbyte(solo_dev, i, TW286X_AV_STAT_ADDR, 654 val = (tw_readbyte(solo_dev, i, TW286x_AV_STAT_ADDR,
630 TW_AV_STAT_ADDR) & 0xf0) >> 4; 655 TW_AV_STAT_ADDR) & 0xf0) >> 4;
631 status |= val << (i * 4); 656 status |= val << (i * 4);
632 } 657 }
@@ -635,7 +660,8 @@ u16 tw28_get_audio_status(struct solo_dev *solo_dev)
635} 660}
636#endif 661#endif
637 662
638int tw28_set_ctrl_val(struct solo_dev *solo_dev, u32 ctrl, u8 ch, s32 val) 663int tw28_set_ctrl_val(struct solo_dev *solo_dev, u32 ctrl, u8 ch,
664 s32 val)
639{ 665{
640 char sval; 666 char sval;
641 u8 chip_num; 667 u8 chip_num;
@@ -676,6 +702,7 @@ int tw28_set_ctrl_val(struct solo_dev *solo_dev, u32 ctrl, u8 ch, s32 val)
676 break; 702 break;
677 703
678 case V4L2_CID_SATURATION: 704 case V4L2_CID_SATURATION:
705 /* 286x chips have a U and V component for saturation */
679 if (is_tw286x(solo_dev, chip_num)) { 706 if (is_tw286x(solo_dev, chip_num)) {
680 solo_i2c_writebyte(solo_dev, SOLO_I2C_TW, 707 solo_i2c_writebyte(solo_dev, SOLO_I2C_TW,
681 TW_CHIP_OFFSET_ADDR(chip_num), 708 TW_CHIP_OFFSET_ADDR(chip_num),
diff --git a/drivers/staging/media/solo6x10/tw28.h b/drivers/staging/media/solo6x10/tw28.h
index a44a03afbd30..a03b429d44d4 100644
--- a/drivers/staging/media/solo6x10/tw28.h
+++ b/drivers/staging/media/solo6x10/tw28.h
@@ -1,6 +1,11 @@
1/* 1/*
2 * Copyright (C) 2010 Bluecherry, LLC www.bluecherrydvr.com 2 * Copyright (C) 2010-2013 Bluecherry, LLC <http://www.bluecherrydvr.com>
3 * Copyright (C) 2010 Ben Collins <bcollins@bluecherry.net> 3 *
4 * Original author:
5 * Ben Collins <bcollins@ubuntu.com>
6 *
7 * Additional work by:
8 * John Brooks <john.brooks@bluecherry.net>
4 * 9 *
5 * This program is free software; you can redistribute it and/or modify 10 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by 11 * it under the terms of the GNU General Public License as published by
@@ -36,7 +41,7 @@
36#define TW_AUDIO_INPUT_GAIN_ADDR(n) (0x60 + ((n > 1) ? 1 : 0)) 41#define TW_AUDIO_INPUT_GAIN_ADDR(n) (0x60 + ((n > 1) ? 1 : 0))
37 42
38/* tw286x */ 43/* tw286x */
39#define TW286X_AV_STAT_ADDR 0xfd 44#define TW286x_AV_STAT_ADDR 0xfd
40#define TW286x_HUE_ADDR(n) (0x06 | ((n) << 4)) 45#define TW286x_HUE_ADDR(n) (0x06 | ((n) << 4))
41#define TW286x_SATURATIONU_ADDR(n) (0x04 | ((n) << 4)) 46#define TW286x_SATURATIONU_ADDR(n) (0x04 | ((n) << 4))
42#define TW286x_SATURATIONV_ADDR(n) (0x05 | ((n) << 4)) 47#define TW286x_SATURATIONV_ADDR(n) (0x05 | ((n) << 4))
diff --git a/drivers/staging/media/solo6x10/v4l2-enc.c b/drivers/staging/media/solo6x10/v4l2-enc.c
index 310b126e1288..bb4d60a4c723 100644
--- a/drivers/staging/media/solo6x10/v4l2-enc.c
+++ b/drivers/staging/media/solo6x10/v4l2-enc.c
@@ -1,6 +1,11 @@
1/* 1/*
2 * Copyright (C) 2010 Bluecherry, LLC www.bluecherrydvr.com 2 * Copyright (C) 2010-2013 Bluecherry, LLC <http://www.bluecherrydvr.com>
3 * Copyright (C) 2010 Ben Collins <bcollins@bluecherry.net> 3 *
4 * Original author:
5 * Ben Collins <bcollins@ubuntu.com>
6 *
7 * Additional work by:
8 * John Brooks <john.brooks@bluecherry.net>
4 * 9 *
5 * This program is free software; you can redistribute it and/or modify 10 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by 11 * it under the terms of the GNU General Public License as published by
@@ -21,33 +26,100 @@
21#include <linux/module.h> 26#include <linux/module.h>
22#include <linux/kthread.h> 27#include <linux/kthread.h>
23#include <linux/freezer.h> 28#include <linux/freezer.h>
29
24#include <media/v4l2-ioctl.h> 30#include <media/v4l2-ioctl.h>
25#include <media/v4l2-common.h> 31#include <media/v4l2-common.h>
26#include <media/videobuf-dma-sg.h> 32#include <media/videobuf-dma-sg.h>
33
27#include "solo6x10.h" 34#include "solo6x10.h"
28#include "tw28.h" 35#include "tw28.h"
29#include "solo6x10-jpeg.h" 36#include "solo6x10-jpeg.h"
30 37
31#define MIN_VID_BUFFERS 4 38#define MIN_VID_BUFFERS 2
32#define FRAME_BUF_SIZE (128 * 1024) 39#define FRAME_BUF_SIZE (196 * 1024)
33#define MP4_QS 16 40#define MP4_QS 16
41#define DMA_ALIGN 4096
34 42
35static int solo_enc_thread(void *data); 43enum solo_enc_types {
36 44 SOLO_ENC_TYPE_STD,
37extern unsigned video_nr; 45 SOLO_ENC_TYPE_EXT,
46};
38 47
39struct solo_enc_fh { 48struct solo_enc_fh {
40 struct solo_enc_dev *enc; 49 struct solo_enc_dev *enc;
41 u32 fmt; 50 u32 fmt;
42 u16 rd_idx;
43 u8 enc_on; 51 u8 enc_on;
44 enum solo_enc_types type; 52 enum solo_enc_types type;
45 struct videobuf_queue vidq; 53 struct videobuf_queue vidq;
46 struct list_head vidq_active; 54 struct list_head vidq_active;
47 struct task_struct *kthread; 55 int desc_count;
48 struct p2m_desc desc[SOLO_NR_P2M_DESC]; 56 int desc_nelts;
57 struct solo_p2m_desc *desc_items;
58 dma_addr_t desc_dma;
59 spinlock_t av_lock;
60 struct list_head list;
61};
62
63struct solo_videobuf {
64 struct videobuf_buffer vb;
65 unsigned int flags;
66};
67
68/* 6010 M4V */
69static unsigned char vop_6010_ntsc_d1[] = {
70 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x20,
71 0x02, 0x48, 0x1d, 0xc0, 0x00, 0x40, 0x00, 0x40,
72 0x00, 0x40, 0x00, 0x80, 0x00, 0x97, 0x53, 0x04,
73 0x1f, 0x4c, 0x58, 0x10, 0xf0, 0x71, 0x18, 0x3f,
74};
75
76static unsigned char vop_6010_ntsc_cif[] = {
77 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x20,
78 0x02, 0x48, 0x1d, 0xc0, 0x00, 0x40, 0x00, 0x40,
79 0x00, 0x40, 0x00, 0x80, 0x00, 0x97, 0x53, 0x04,
80 0x1f, 0x4c, 0x2c, 0x10, 0x78, 0x51, 0x18, 0x3f,
81};
82
83static unsigned char vop_6010_pal_d1[] = {
84 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x20,
85 0x02, 0x48, 0x15, 0xc0, 0x00, 0x40, 0x00, 0x40,
86 0x00, 0x40, 0x00, 0x80, 0x00, 0x97, 0x53, 0x04,
87 0x1f, 0x4c, 0x58, 0x11, 0x20, 0x71, 0x18, 0x3f,
88};
89
90static unsigned char vop_6010_pal_cif[] = {
91 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x20,
92 0x02, 0x48, 0x15, 0xc0, 0x00, 0x40, 0x00, 0x40,
93 0x00, 0x40, 0x00, 0x80, 0x00, 0x97, 0x53, 0x04,
94 0x1f, 0x4c, 0x2c, 0x10, 0x90, 0x51, 0x18, 0x3f,
95};
96
97/* 6110 h.264 */
98static unsigned char vop_6110_ntsc_d1[] = {
99 0x00, 0x00, 0x00, 0x01, 0x67, 0x42, 0x00, 0x1e,
100 0x9a, 0x74, 0x05, 0x81, 0xec, 0x80, 0x00, 0x00,
101 0x00, 0x01, 0x68, 0xce, 0x32, 0x28, 0x00, 0x00,
102};
103
104static unsigned char vop_6110_ntsc_cif[] = {
105 0x00, 0x00, 0x00, 0x01, 0x67, 0x42, 0x00, 0x1e,
106 0x9a, 0x74, 0x0b, 0x0f, 0xc8, 0x00, 0x00, 0x00,
107 0x01, 0x68, 0xce, 0x32, 0x28, 0x00, 0x00, 0x00,
108};
109
110static unsigned char vop_6110_pal_d1[] = {
111 0x00, 0x00, 0x00, 0x01, 0x67, 0x42, 0x00, 0x1e,
112 0x9a, 0x74, 0x05, 0x80, 0x93, 0x20, 0x00, 0x00,
113 0x00, 0x01, 0x68, 0xce, 0x32, 0x28, 0x00, 0x00,
114};
115
116static unsigned char vop_6110_pal_cif[] = {
117 0x00, 0x00, 0x00, 0x01, 0x67, 0x42, 0x00, 0x1e,
118 0x9a, 0x74, 0x0b, 0x04, 0xb2, 0x00, 0x00, 0x00,
119 0x01, 0x68, 0xce, 0x32, 0x28, 0x00, 0x00, 0x00,
49}; 120};
50 121
122
51static const u32 solo_user_ctrls[] = { 123static const u32 solo_user_ctrls[] = {
52 V4L2_CID_BRIGHTNESS, 124 V4L2_CID_BRIGHTNESS,
53 V4L2_CID_CONTRAST, 125 V4L2_CID_CONTRAST,
@@ -82,79 +154,179 @@ static const u32 *solo_ctrl_classes[] = {
82 NULL 154 NULL
83}; 155};
84 156
157struct vop_header {
158 /* VE_STATUS0 */
159 u32 mpeg_size:20, sad_motion_flag:1, video_motion_flag:1, vop_type:2,
160 channel:5, source_fl:1, interlace:1, progressive:1;
161
162 /* VE_STATUS1 */
163 u32 vsize:8, hsize:8, last_queue:4, nop0:8, scale:4;
164
165 /* VE_STATUS2 */
166 u32 mpeg_off;
167
168 /* VE_STATUS3 */
169 u32 jpeg_off;
170
171 /* VE_STATUS4 */
172 u32 jpeg_size:20, interval:10, nop1:2;
173
174 /* VE_STATUS5/6 */
175 u32 sec, usec;
176
177 /* VE_STATUS7/8/9 */
178 u32 nop2[3];
179
180 /* VE_STATUS10 */
181 u32 mpeg_size_alt:20, nop3:12;
182
183 u32 end_nops[5];
184} __packed;
185
186struct solo_enc_buf {
187 enum solo_enc_types type;
188 struct vop_header *vh;
189 int motion;
190};
191
85static int solo_is_motion_on(struct solo_enc_dev *solo_enc) 192static int solo_is_motion_on(struct solo_enc_dev *solo_enc)
86{ 193{
87 struct solo_dev *solo_dev = solo_enc->solo_dev; 194 struct solo_dev *solo_dev = solo_enc->solo_dev;
88 u8 ch = solo_enc->ch;
89 195
90 if (solo_dev->motion_mask & (1 << ch)) 196 return (solo_dev->motion_mask >> solo_enc->ch) & 1;
91 return 1; 197}
92 return 0; 198
199static int solo_motion_detected(struct solo_enc_dev *solo_enc)
200{
201 struct solo_dev *solo_dev = solo_enc->solo_dev;
202 unsigned long flags;
203 u32 ch_mask = 1 << solo_enc->ch;
204 int ret = 0;
205
206 spin_lock_irqsave(&solo_enc->motion_lock, flags);
207 if (solo_reg_read(solo_dev, SOLO_VI_MOT_STATUS) & ch_mask) {
208 solo_reg_write(solo_dev, SOLO_VI_MOT_CLEAR, ch_mask);
209 ret = 1;
210 }
211 spin_unlock_irqrestore(&solo_enc->motion_lock, flags);
212
213 return ret;
93} 214}
94 215
95static void solo_motion_toggle(struct solo_enc_dev *solo_enc, int on) 216static void solo_motion_toggle(struct solo_enc_dev *solo_enc, int on)
96{ 217{
97 struct solo_dev *solo_dev = solo_enc->solo_dev; 218 struct solo_dev *solo_dev = solo_enc->solo_dev;
98 u8 ch = solo_enc->ch; 219 u32 mask = 1 << solo_enc->ch;
220 unsigned long flags;
99 221
100 spin_lock(&solo_enc->lock); 222 spin_lock_irqsave(&solo_enc->motion_lock, flags);
101 223
102 if (on) 224 if (on)
103 solo_dev->motion_mask |= (1 << ch); 225 solo_dev->motion_mask |= mask;
104 else 226 else
105 solo_dev->motion_mask &= ~(1 << ch); 227 solo_dev->motion_mask &= ~mask;
106 228
107 /* Do this regardless of if we are turning on or off */ 229 solo_reg_write(solo_dev, SOLO_VI_MOT_CLEAR, mask);
108 solo_reg_write(solo_enc->solo_dev, SOLO_VI_MOT_CLEAR,
109 1 << solo_enc->ch);
110 solo_enc->motion_detected = 0;
111 230
112 solo_reg_write(solo_dev, SOLO_VI_MOT_ADR, 231 solo_reg_write(solo_dev, SOLO_VI_MOT_ADR,
113 SOLO_VI_MOTION_EN(solo_dev->motion_mask) | 232 SOLO_VI_MOTION_EN(solo_dev->motion_mask) |
114 (SOLO_MOTION_EXT_ADDR(solo_dev) >> 16)); 233 (SOLO_MOTION_EXT_ADDR(solo_dev) >> 16));
115 234
116 if (solo_dev->motion_mask) 235 spin_unlock_irqrestore(&solo_enc->motion_lock, flags);
117 solo_irq_on(solo_dev, SOLO_IRQ_MOTION);
118 else
119 solo_irq_off(solo_dev, SOLO_IRQ_MOTION);
120
121 spin_unlock(&solo_enc->lock);
122} 236}
123 237
124/* Should be called with solo_enc->lock held */ 238/* MUST be called with solo_enc->enable_lock held */
125static void solo_update_mode(struct solo_enc_dev *solo_enc) 239static void solo_update_mode(struct solo_enc_dev *solo_enc)
126{ 240{
127 struct solo_dev *solo_dev = solo_enc->solo_dev; 241 struct solo_dev *solo_dev = solo_enc->solo_dev;
128 242 int vop_len;
129 assert_spin_locked(&solo_enc->lock); 243 unsigned char *vop;
130 244
131 solo_enc->interlaced = (solo_enc->mode & 0x08) ? 1 : 0; 245 solo_enc->interlaced = (solo_enc->mode & 0x08) ? 1 : 0;
132 solo_enc->bw_weight = max(solo_dev->fps / solo_enc->interval, 1); 246 solo_enc->bw_weight = max(solo_dev->fps / solo_enc->interval, 1);
133 247
134 switch (solo_enc->mode) { 248 if (solo_enc->mode == SOLO_ENC_MODE_CIF) {
135 case SOLO_ENC_MODE_CIF:
136 solo_enc->width = solo_dev->video_hsize >> 1; 249 solo_enc->width = solo_dev->video_hsize >> 1;
137 solo_enc->height = solo_dev->video_vsize; 250 solo_enc->height = solo_dev->video_vsize;
138 break; 251 if (solo_dev->type == SOLO_DEV_6110) {
139 case SOLO_ENC_MODE_D1: 252 if (solo_dev->video_type == SOLO_VO_FMT_TYPE_NTSC) {
253 vop = vop_6110_ntsc_cif;
254 vop_len = sizeof(vop_6110_ntsc_cif);
255 } else {
256 vop = vop_6110_pal_cif;
257 vop_len = sizeof(vop_6110_pal_cif);
258 }
259 } else {
260 if (solo_dev->video_type == SOLO_VO_FMT_TYPE_NTSC) {
261 vop = vop_6010_ntsc_cif;
262 vop_len = sizeof(vop_6010_ntsc_cif);
263 } else {
264 vop = vop_6010_pal_cif;
265 vop_len = sizeof(vop_6010_pal_cif);
266 }
267 }
268 } else {
140 solo_enc->width = solo_dev->video_hsize; 269 solo_enc->width = solo_dev->video_hsize;
141 solo_enc->height = solo_dev->video_vsize << 1; 270 solo_enc->height = solo_dev->video_vsize << 1;
142 solo_enc->bw_weight <<= 2; 271 solo_enc->bw_weight <<= 2;
143 break; 272 if (solo_dev->type == SOLO_DEV_6110) {
144 default: 273 if (solo_dev->video_type == SOLO_VO_FMT_TYPE_NTSC) {
145 WARN(1, "mode is unknown\n"); 274 vop = vop_6110_ntsc_d1;
275 vop_len = sizeof(vop_6110_ntsc_d1);
276 } else {
277 vop = vop_6110_pal_d1;
278 vop_len = sizeof(vop_6110_pal_d1);
279 }
280 } else {
281 if (solo_dev->video_type == SOLO_VO_FMT_TYPE_NTSC) {
282 vop = vop_6010_ntsc_d1;
283 vop_len = sizeof(vop_6010_ntsc_d1);
284 } else {
285 vop = vop_6010_pal_d1;
286 vop_len = sizeof(vop_6010_pal_d1);
287 }
288 }
146 } 289 }
290
291 memcpy(solo_enc->vop, vop, vop_len);
292
293 /* Some fixups for 6010/M4V */
294 if (solo_dev->type == SOLO_DEV_6010) {
295 u16 fps = solo_dev->fps * 1000;
296 u16 interval = solo_enc->interval * 1000;
297
298 vop = solo_enc->vop;
299
300 /* Frame rate and interval */
301 vop[22] = fps >> 4;
302 vop[23] = ((fps << 4) & 0xf0) | 0x0c
303 | ((interval >> 13) & 0x3);
304 vop[24] = (interval >> 5) & 0xff;
305 vop[25] = ((interval << 3) & 0xf8) | 0x04;
306 }
307
308 solo_enc->vop_len = vop_len;
309
310 /* Now handle the jpeg header */
311 vop = solo_enc->jpeg_header;
312 vop[SOF0_START + 5] = 0xff & (solo_enc->height >> 8);
313 vop[SOF0_START + 6] = 0xff & solo_enc->height;
314 vop[SOF0_START + 7] = 0xff & (solo_enc->width >> 8);
315 vop[SOF0_START + 8] = 0xff & solo_enc->width;
316
317 memcpy(vop + DQT_START,
318 jpeg_dqt[solo_g_jpeg_qp(solo_dev, solo_enc->ch)], DQT_LEN);
147} 319}
148 320
149/* Should be called with solo_enc->lock held */ 321/* MUST be called with solo_enc->enable_lock held */
150static int solo_enc_on(struct solo_enc_fh *fh) 322static int __solo_enc_on(struct solo_enc_fh *fh)
151{ 323{
152 struct solo_enc_dev *solo_enc = fh->enc; 324 struct solo_enc_dev *solo_enc = fh->enc;
153 u8 ch = solo_enc->ch; 325 u8 ch = solo_enc->ch;
154 struct solo_dev *solo_dev = solo_enc->solo_dev; 326 struct solo_dev *solo_dev = solo_enc->solo_dev;
155 u8 interval; 327 u8 interval;
156 328
157 assert_spin_locked(&solo_enc->lock); 329 BUG_ON(!mutex_is_locked(&solo_enc->enable_lock));
158 330
159 if (fh->enc_on) 331 if (fh->enc_on)
160 return 0; 332 return 0;
@@ -170,13 +342,20 @@ static int solo_enc_on(struct solo_enc_fh *fh)
170 } 342 }
171 343
172 fh->enc_on = 1; 344 fh->enc_on = 1;
173 fh->rd_idx = solo_enc->solo_dev->enc_wr_idx; 345 list_add(&fh->list, &solo_enc->listeners);
174 346
175 if (fh->type == SOLO_ENC_TYPE_EXT) 347 if (fh->type == SOLO_ENC_TYPE_EXT)
176 solo_reg_write(solo_dev, SOLO_CAP_CH_COMP_ENA_E(ch), 1); 348 solo_reg_write(solo_dev, SOLO_CAP_CH_COMP_ENA_E(ch), 1);
177 349
178 if (atomic_inc_return(&solo_enc->readers) > 1) 350 /* Reset the encoder if we are the first mpeg reader, else only reset
351 * on the first mjpeg reader. */
352 if (fh->fmt == V4L2_PIX_FMT_MPEG) {
353 atomic_inc(&solo_enc->readers);
354 if (atomic_inc_return(&solo_enc->mpeg_readers) > 1)
355 return 0;
356 } else if (atomic_inc_return(&solo_enc->readers) > 1) {
179 return 0; 357 return 0;
358 }
180 359
181 /* Disable all encoding for this channel */ 360 /* Disable all encoding for this channel */
182 solo_reg_write(solo_dev, SOLO_CAP_CH_SCALE(ch), 0); 361 solo_reg_write(solo_dev, SOLO_CAP_CH_SCALE(ch), 0);
@@ -203,701 +382,414 @@ static int solo_enc_on(struct solo_enc_fh *fh)
203 /* Enables the standard encoder */ 382 /* Enables the standard encoder */
204 solo_reg_write(solo_dev, SOLO_CAP_CH_SCALE(ch), solo_enc->mode); 383 solo_reg_write(solo_dev, SOLO_CAP_CH_SCALE(ch), solo_enc->mode);
205 384
206 /* Settle down Beavis... */
207 mdelay(10);
208
209 return 0; 385 return 0;
210} 386}
211 387
212static void solo_enc_off(struct solo_enc_fh *fh) 388static int solo_enc_on(struct solo_enc_fh *fh)
213{ 389{
214 struct solo_enc_dev *solo_enc = fh->enc; 390 struct solo_enc_dev *solo_enc = fh->enc;
215 struct solo_dev *solo_dev = solo_enc->solo_dev; 391 int ret;
216
217 if (!fh->enc_on)
218 return;
219
220 if (fh->kthread) {
221 kthread_stop(fh->kthread);
222 fh->kthread = NULL;
223 }
224
225 solo_dev->enc_bw_remain += solo_enc->bw_weight;
226 fh->enc_on = 0;
227 392
228 if (atomic_dec_return(&solo_enc->readers) > 0) 393 mutex_lock(&solo_enc->enable_lock);
229 return; 394 ret = __solo_enc_on(fh);
395 mutex_unlock(&solo_enc->enable_lock);
230 396
231 solo_reg_write(solo_dev, SOLO_CAP_CH_SCALE(solo_enc->ch), 0); 397 return ret;
232 solo_reg_write(solo_dev, SOLO_CAP_CH_COMP_ENA_E(solo_enc->ch), 0);
233} 398}
234 399
235static int solo_start_fh_thread(struct solo_enc_fh *fh) 400static void __solo_enc_off(struct solo_enc_fh *fh)
236{ 401{
237 struct solo_enc_dev *solo_enc = fh->enc; 402 struct solo_enc_dev *solo_enc = fh->enc;
403 struct solo_dev *solo_dev = solo_enc->solo_dev;
238 404
239 fh->kthread = kthread_run(solo_enc_thread, fh, SOLO6X10_NAME "_enc"); 405 BUG_ON(!mutex_is_locked(&solo_enc->enable_lock));
240
241 /* Oops, we had a problem */
242 if (IS_ERR(fh->kthread)) {
243 spin_lock(&solo_enc->lock);
244 solo_enc_off(fh);
245 spin_unlock(&solo_enc->lock);
246
247 return PTR_ERR(fh->kthread);
248 }
249 406
250 return 0; 407 if (!fh->enc_on)
251} 408 return;
252 409
253static void enc_reset_gop(struct solo_dev *solo_dev, u8 ch) 410 list_del(&fh->list);
254{ 411 fh->enc_on = 0;
255 BUG_ON(ch >= solo_dev->nr_chans);
256 solo_reg_write(solo_dev, SOLO_VE_CH_GOP(ch), 1);
257 solo_dev->v4l2_enc[ch]->reset_gop = 1;
258}
259 412
260static int enc_gop_reset(struct solo_dev *solo_dev, u8 ch, u8 vop) 413 if (fh->fmt == V4L2_PIX_FMT_MPEG)
261{ 414 atomic_dec(&solo_enc->mpeg_readers);
262 BUG_ON(ch >= solo_dev->nr_chans);
263 if (!solo_dev->v4l2_enc[ch]->reset_gop)
264 return 0;
265 if (vop)
266 return 1;
267 solo_dev->v4l2_enc[ch]->reset_gop = 0;
268 solo_reg_write(solo_dev, SOLO_VE_CH_GOP(ch),
269 solo_dev->v4l2_enc[ch]->gop);
270 return 0;
271}
272 415
273static void enc_write_sg(struct scatterlist *sglist, void *buf, int size) 416 if (atomic_dec_return(&solo_enc->readers) > 0)
274{ 417 return;
275 struct scatterlist *sg;
276 u8 *src = buf;
277 418
278 for (sg = sglist; sg && size > 0; sg = sg_next(sg)) { 419 solo_dev->enc_bw_remain += solo_enc->bw_weight;
279 u8 *p = sg_virt(sg);
280 size_t len = sg_dma_len(sg);
281 int i;
282 420
283 for (i = 0; i < len && size; i++) 421 solo_reg_write(solo_dev, SOLO_CAP_CH_SCALE(solo_enc->ch), 0);
284 p[i] = *(src++); 422 solo_reg_write(solo_dev, SOLO_CAP_CH_COMP_ENA_E(solo_enc->ch), 0);
285 }
286} 423}
287 424
288static int enc_get_mpeg_dma_sg(struct solo_dev *solo_dev, 425static void solo_enc_off(struct solo_enc_fh *fh)
289 struct p2m_desc *desc,
290 struct scatterlist *sglist, int skip,
291 unsigned int off, unsigned int size)
292{ 426{
293 int ret; 427 struct solo_enc_dev *solo_enc = fh->enc;
294
295 if (off > SOLO_MP4E_EXT_SIZE(solo_dev))
296 return -EINVAL;
297
298 if (off + size <= SOLO_MP4E_EXT_SIZE(solo_dev)) {
299 return solo_p2m_dma_sg(solo_dev, SOLO_P2M_DMA_ID_MP4E,
300 desc, 0, sglist, skip,
301 SOLO_MP4E_EXT_ADDR(solo_dev) + off, size);
302 }
303
304 /* Buffer wrap */
305 ret = solo_p2m_dma_sg(solo_dev, SOLO_P2M_DMA_ID_MP4E, desc, 0,
306 sglist, skip, SOLO_MP4E_EXT_ADDR(solo_dev) + off,
307 SOLO_MP4E_EXT_SIZE(solo_dev) - off);
308
309 ret |= solo_p2m_dma_sg(solo_dev, SOLO_P2M_DMA_ID_MP4E, desc, 0,
310 sglist, skip + SOLO_MP4E_EXT_SIZE(solo_dev) - off,
311 SOLO_MP4E_EXT_ADDR(solo_dev),
312 size + off - SOLO_MP4E_EXT_SIZE(solo_dev));
313 428
314 return ret; 429 mutex_lock(&solo_enc->enable_lock);
430 __solo_enc_off(fh);
431 mutex_unlock(&solo_enc->enable_lock);
315} 432}
316 433
317static int enc_get_mpeg_dma_t(struct solo_dev *solo_dev, 434static int enc_get_mpeg_dma(struct solo_dev *solo_dev, dma_addr_t dma,
318 dma_addr_t buf, unsigned int off, 435 unsigned int off, unsigned int size)
319 unsigned int size)
320{ 436{
321 int ret; 437 int ret;
322 438
323 if (off > SOLO_MP4E_EXT_SIZE(solo_dev)) 439 if (off > SOLO_MP4E_EXT_SIZE(solo_dev))
324 return -EINVAL; 440 return -EINVAL;
325 441
442 /* Single shot */
326 if (off + size <= SOLO_MP4E_EXT_SIZE(solo_dev)) { 443 if (off + size <= SOLO_MP4E_EXT_SIZE(solo_dev)) {
327 return solo_p2m_dma_t(solo_dev, SOLO_P2M_DMA_ID_MP4E, 0, buf, 444 return solo_p2m_dma_t(solo_dev, 0, dma,
328 SOLO_MP4E_EXT_ADDR(solo_dev) + off, size); 445 SOLO_MP4E_EXT_ADDR(solo_dev) + off, size,
446 0, 0);
329 } 447 }
330 448
331 /* Buffer wrap */ 449 /* Buffer wrap */
332 ret = solo_p2m_dma_t(solo_dev, SOLO_P2M_DMA_ID_MP4E, 0, buf, 450 ret = solo_p2m_dma_t(solo_dev, 0, dma,
333 SOLO_MP4E_EXT_ADDR(solo_dev) + off, 451 SOLO_MP4E_EXT_ADDR(solo_dev) + off,
334 SOLO_MP4E_EXT_SIZE(solo_dev) - off); 452 SOLO_MP4E_EXT_SIZE(solo_dev) - off, 0, 0);
335
336 ret |= solo_p2m_dma_t(solo_dev, SOLO_P2M_DMA_ID_MP4E, 0,
337 buf + SOLO_MP4E_EXT_SIZE(solo_dev) - off,
338 SOLO_MP4E_EXT_ADDR(solo_dev),
339 size + off - SOLO_MP4E_EXT_SIZE(solo_dev));
340
341 return ret;
342}
343 453
344static int enc_get_mpeg_dma(struct solo_dev *solo_dev, void *buf, 454 if (!ret) {
345 unsigned int off, unsigned int size) 455 ret = solo_p2m_dma_t(solo_dev, 0,
346{ 456 dma + SOLO_MP4E_EXT_SIZE(solo_dev) - off,
347 int ret; 457 SOLO_MP4E_EXT_ADDR(solo_dev),
348 458 size + off - SOLO_MP4E_EXT_SIZE(solo_dev), 0, 0);
349 dma_addr_t dma_addr = pci_map_single(solo_dev->pdev, buf, size, 459 }
350 PCI_DMA_FROMDEVICE);
351 ret = enc_get_mpeg_dma_t(solo_dev, dma_addr, off, size);
352 pci_unmap_single(solo_dev->pdev, dma_addr, size, PCI_DMA_FROMDEVICE);
353 460
354 return ret; 461 return ret;
355} 462}
356 463
357static int enc_get_jpeg_dma_sg(struct solo_dev *solo_dev, 464/* Build a descriptor queue out of an SG list and send it to the P2M for
358 struct p2m_desc *desc, 465 * processing. */
359 struct scatterlist *sglist, int skip, 466static int solo_send_desc(struct solo_enc_fh *fh, int skip,
360 unsigned int off, unsigned int size) 467 struct videobuf_dmabuf *vbuf, int off, int size,
468 unsigned int base, unsigned int base_size)
361{ 469{
470 struct solo_dev *solo_dev = fh->enc->solo_dev;
471 struct scatterlist *sg;
472 int i;
362 int ret; 473 int ret;
363 474
364 if (off > SOLO_JPEG_EXT_SIZE(solo_dev)) 475 if (WARN_ON_ONCE(size > FRAME_BUF_SIZE))
365 return -EINVAL; 476 return -EINVAL;
366 477
367 if (off + size <= SOLO_JPEG_EXT_SIZE(solo_dev)) { 478 fh->desc_count = 1;
368 return solo_p2m_dma_sg(solo_dev, SOLO_P2M_DMA_ID_JPEG, 479
369 desc, 0, sglist, skip, 480 for_each_sg(vbuf->sglist, sg, vbuf->sglen, i) {
370 SOLO_JPEG_EXT_ADDR(solo_dev) + off, size); 481 struct solo_p2m_desc *desc;
371 } 482 dma_addr_t dma;
372 483 int len;
373 /* Buffer wrap */ 484 int left = base_size - off;
374 ret = solo_p2m_dma_sg(solo_dev, SOLO_P2M_DMA_ID_JPEG, desc, 0, 485
375 sglist, skip, SOLO_JPEG_EXT_ADDR(solo_dev) + off, 486 desc = &fh->desc_items[fh->desc_count++];
376 SOLO_JPEG_EXT_SIZE(solo_dev) - off); 487 dma = sg_dma_address(sg);
488 len = sg_dma_len(sg);
489
490 /* We assume this is smaller than the scatter size */
491 BUG_ON(skip >= len);
492 if (skip) {
493 len -= skip;
494 dma += skip;
495 size -= skip;
496 skip = 0;
497 }
377 498
378 ret |= solo_p2m_dma_sg(solo_dev, SOLO_P2M_DMA_ID_JPEG, desc, 0, 499 len = min(len, size);
379 sglist, skip + SOLO_JPEG_EXT_SIZE(solo_dev) - off,
380 SOLO_JPEG_EXT_ADDR(solo_dev),
381 size + off - SOLO_JPEG_EXT_SIZE(solo_dev));
382 500
383 return ret; 501 if (len <= left) {
384} 502 /* Single descriptor */
503 solo_p2m_fill_desc(desc, 0, dma, base + off,
504 len, 0, 0);
505 } else {
506 /* Buffer wrap */
507 /* XXX: Do these as separate DMA requests, to avoid
508 timeout errors triggered by awkwardly sized
509 descriptors. See
510 <https://github.com/bluecherrydvr/solo6x10/issues/8>
511 */
512 ret = solo_p2m_dma_t(solo_dev, 0, dma, base + off,
513 left, 0, 0);
514 if (ret)
515 return ret;
516
517 ret = solo_p2m_dma_t(solo_dev, 0, dma + left, base,
518 len - left, 0, 0);
519 if (ret)
520 return ret;
521
522 fh->desc_count--;
523 }
385 524
386/* Returns true of __chk is within the first __range bytes of __off */ 525 size -= len;
387#define OFF_IN_RANGE(__off, __range, __chk) \ 526 if (size <= 0)
388 ((__off <= __chk) && ((__off + __range) >= __chk)) 527 break;
389 528
390static void solo_jpeg_header(struct solo_enc_dev *solo_enc, 529 off += len;
391 struct videobuf_dmabuf *vbuf) 530 if (off >= base_size)
392{ 531 off -= base_size;
393 struct scatterlist *sg; 532
394 void *src = jpeg_header; 533 /* Because we may use two descriptors per loop */
395 size_t copied = 0; 534 if (fh->desc_count >= (fh->desc_nelts - 1)) {
396 size_t to_copy = sizeof(jpeg_header); 535 ret = solo_p2m_dma_desc(solo_dev, fh->desc_items,
397 536 fh->desc_dma,
398 for (sg = vbuf->sglist; sg && copied < to_copy; sg = sg_next(sg)) { 537 fh->desc_count - 1);
399 size_t this_copy = min(sg_dma_len(sg), 538 if (ret)
400 (unsigned int)(to_copy - copied)); 539 return ret;
401 u8 *p = sg_virt(sg); 540 fh->desc_count = 1;
402 541 }
403 memcpy(p, src + copied, this_copy);
404
405 if (OFF_IN_RANGE(copied, this_copy, SOF0_START + 5))
406 p[(SOF0_START + 5) - copied] =
407 0xff & (solo_enc->height >> 8);
408 if (OFF_IN_RANGE(copied, this_copy, SOF0_START + 6))
409 p[(SOF0_START + 6) - copied] = 0xff & solo_enc->height;
410 if (OFF_IN_RANGE(copied, this_copy, SOF0_START + 7))
411 p[(SOF0_START + 7) - copied] =
412 0xff & (solo_enc->width >> 8);
413 if (OFF_IN_RANGE(copied, this_copy, SOF0_START + 8))
414 p[(SOF0_START + 8) - copied] = 0xff & solo_enc->width;
415
416 copied += this_copy;
417 } 542 }
418}
419
420static int solo_fill_jpeg(struct solo_enc_fh *fh, struct solo_enc_buf *enc_buf,
421 struct videobuf_buffer *vb,
422 struct videobuf_dmabuf *vbuf)
423{
424 struct solo_dev *solo_dev = fh->enc->solo_dev;
425 int size = enc_buf->jpeg_size;
426
427 /* Copy the header first (direct write) */
428 solo_jpeg_header(fh->enc, vbuf);
429
430 vb->size = size + sizeof(jpeg_header);
431
432 /* Grab the jpeg frame */
433 return enc_get_jpeg_dma_sg(solo_dev, fh->desc, vbuf->sglist,
434 sizeof(jpeg_header),
435 enc_buf->jpeg_off, size);
436}
437
438static inline int vop_interlaced(__le32 *vh)
439{
440 return (__le32_to_cpu(vh[0]) >> 30) & 1;
441}
442 543
443static inline u32 vop_size(__le32 *vh) 544 if (fh->desc_count <= 1)
444{ 545 return 0;
445 return __le32_to_cpu(vh[0]) & 0xFFFFF;
446}
447
448static inline u8 vop_hsize(__le32 *vh)
449{
450 return (__le32_to_cpu(vh[1]) >> 8) & 0xFF;
451}
452
453static inline u8 vop_vsize(__le32 *vh)
454{
455 return __le32_to_cpu(vh[1]) & 0xFF;
456}
457
458/* must be called with *bits % 8 = 0 */
459static void write_bytes(u8 **out, unsigned *bits, const u8 *src, unsigned count)
460{
461 memcpy(*out, src, count);
462 *out += count;
463 *bits += count * 8;
464}
465
466static void write_bits(u8 **out, unsigned *bits, u32 value, unsigned count)
467{
468
469 value <<= 32 - count; // shift to the right
470 546
471 while (count--) { 547 return solo_p2m_dma_desc(solo_dev, fh->desc_items, fh->desc_dma,
472 **out <<= 1; 548 fh->desc_count - 1);
473 **out |= !!(value & (1 << 31)); /* MSB */
474 value <<= 1;
475 if (++(*bits) % 8 == 0)
476 (*out)++;
477 }
478} 549}
479 550
480static void write_ue(u8 **out, unsigned *bits, unsigned value) /* H.264 only */ 551static int solo_fill_jpeg(struct solo_enc_fh *fh, struct videobuf_buffer *vb,
552 struct videobuf_dmabuf *vbuf, struct vop_header *vh)
481{ 553{
482 uint32_t max = 0, cnt = 0; 554 struct solo_enc_dev *solo_enc = fh->enc;
555 struct solo_dev *solo_dev = solo_enc->solo_dev;
556 struct solo_videobuf *svb = (struct solo_videobuf *)vb;
557 int frame_size;
483 558
484 while (value > max) { 559 svb->flags |= V4L2_BUF_FLAG_KEYFRAME;
485 max = (max + 2) * 2 - 2;
486 cnt++;
487 }
488 write_bits(out, bits, 1, cnt + 1);
489 write_bits(out, bits, ~(max - value), cnt);
490}
491 560
492static void write_se(u8 **out, unsigned *bits, int value) /* H.264 only */ 561 if (vb->bsize < (vh->jpeg_size + solo_enc->jpeg_len))
493{ 562 return -EIO;
494 if (value <= 0)
495 write_ue(out, bits, -value * 2);
496 else
497 write_ue(out, bits, value * 2 - 1);
498}
499 563
500static void write_mpeg4_end(u8 **out, unsigned *bits) 564 vb->width = solo_enc->width;
501{ 565 vb->height = solo_enc->height;
502 write_bits(out, bits, 0, 1); 566 vb->size = vh->jpeg_size + solo_enc->jpeg_len;
503 /* align on 32-bit boundary */
504 if (*bits % 32)
505 write_bits(out, bits, 0xFFFFFFFF, 32 - *bits % 32);
506}
507 567
508static void write_h264_end(u8 **out, unsigned *bits, int align) 568 sg_copy_from_buffer(vbuf->sglist, vbuf->sglen,
509{ 569 solo_enc->jpeg_header,
510 write_bits(out, bits, 1, 1); 570 solo_enc->jpeg_len);
511 while ((*bits) % 8)
512 write_bits(out, bits, 0, 1);
513 if (align)
514 while ((*bits) % 32)
515 write_bits(out, bits, 0, 1);
516}
517 571
518static void mpeg4_write_vol(u8 **out, struct solo_dev *solo_dev, 572 frame_size = (vh->jpeg_size + solo_enc->jpeg_len + (DMA_ALIGN - 1))
519 __le32 *vh, unsigned fps, unsigned interval) 573 & ~(DMA_ALIGN - 1);
520{
521 static const u8 hdr[] = {
522 0, 0, 1, 0x00 /* video_object_start_code */,
523 0, 0, 1, 0x20 /* video_object_layer_start_code */
524 };
525 unsigned bits = 0;
526 unsigned width = vop_hsize(vh) << 4;
527 unsigned height = vop_vsize(vh) << 4;
528 unsigned interlaced = vop_interlaced(vh);
529
530 write_bytes(out, &bits, hdr, sizeof(hdr));
531 write_bits(out, &bits, 0, 1); /* random_accessible_vol */
532 write_bits(out, &bits, 0x04, 8); /* video_object_type_indication: main */
533 write_bits(out, &bits, 1, 1); /* is_object_layer_identifier */
534 write_bits(out, &bits, 2, 4); /* video_object_layer_verid: table V2-39 */
535 write_bits(out, &bits, 0, 3); /* video_object_layer_priority */
536 if (solo_dev->video_type == SOLO_VO_FMT_TYPE_NTSC)
537 write_bits(out, &bits, 3, 4); /* aspect_ratio_info, assuming 4:3 */
538 else
539 write_bits(out, &bits, 2, 4);
540 write_bits(out, &bits, 1, 1); /* vol_control_parameters */
541 write_bits(out, &bits, 1, 2); /* chroma_format: 4:2:0 */
542 write_bits(out, &bits, 1, 1); /* low_delay */
543 write_bits(out, &bits, 0, 1); /* vbv_parameters */
544 write_bits(out, &bits, 0, 2); /* video_object_layer_shape: rectangular */
545 write_bits(out, &bits, 1, 1); /* marker_bit */
546 write_bits(out, &bits, fps, 16); /* vop_time_increment_resolution */
547 write_bits(out, &bits, 1, 1); /* marker_bit */
548 write_bits(out, &bits, 1, 1); /* fixed_vop_rate */
549 write_bits(out, &bits, interval, 15); /* fixed_vop_time_increment */
550 write_bits(out, &bits, 1, 1); /* marker_bit */
551 write_bits(out, &bits, width, 13); /* video_object_layer_width */
552 write_bits(out, &bits, 1, 1); /* marker_bit */
553 write_bits(out, &bits, height, 13); /* video_object_layer_height */
554 write_bits(out, &bits, 1, 1); /* marker_bit */
555 write_bits(out, &bits, interlaced, 1); /* interlaced */
556 write_bits(out, &bits, 1, 1); /* obmc_disable */
557 write_bits(out, &bits, 0, 2); /* sprite_enable */
558 write_bits(out, &bits, 0, 1); /* not_8_bit */
559 write_bits(out, &bits, 1, 0); /* quant_type */
560 write_bits(out, &bits, 0, 1); /* load_intra_quant_mat */
561 write_bits(out, &bits, 0, 1); /* load_nonintra_quant_mat */
562 write_bits(out, &bits, 0, 1); /* quarter_sample */
563 write_bits(out, &bits, 1, 1); /* complexity_estimation_disable */
564 write_bits(out, &bits, 1, 1); /* resync_marker_disable */
565 write_bits(out, &bits, 0, 1); /* data_partitioned */
566 write_bits(out, &bits, 0, 1); /* newpred_enable */
567 write_bits(out, &bits, 0, 1); /* reduced_resolution_vop_enable */
568 write_bits(out, &bits, 0, 1); /* scalability */
569 write_mpeg4_end(out, &bits);
570}
571 574
572static void h264_write_vol(u8 **out, struct solo_dev *solo_dev, __le32 *vh) 575 return solo_send_desc(fh, solo_enc->jpeg_len, vbuf, vh->jpeg_off,
573{ 576 frame_size, SOLO_JPEG_EXT_ADDR(solo_dev),
574 static const u8 sps[] = { 577 SOLO_JPEG_EXT_SIZE(solo_dev));
575 0, 0, 0, 1 /* start code */, 0x67, 66 /* profile_idc */,
576 0 /* constraints */, 30 /* level_idc */
577 };
578 static const u8 pps[] = {
579 0, 0, 0, 1 /* start code */, 0x68
580 };
581
582 unsigned bits = 0;
583 unsigned mbs_w = vop_hsize(vh);
584 unsigned mbs_h = vop_vsize(vh);
585
586 write_bytes(out, &bits, sps, sizeof(sps));
587 write_ue(out, &bits, 0); /* seq_parameter_set_id */
588 write_ue(out, &bits, 5); /* log2_max_frame_num_minus4 */
589 write_ue(out, &bits, 0); /* pic_order_cnt_type */
590 write_ue(out, &bits, 6); /* log2_max_pic_order_cnt_lsb_minus4 */
591 write_ue(out, &bits, 1); /* max_num_ref_frames */
592 write_bits(out, &bits, 0, 1); /* gaps_in_frame_num_value_allowed_flag */
593 write_ue(out, &bits, mbs_w - 1); /* pic_width_in_mbs_minus1 */
594 write_ue(out, &bits, mbs_h - 1); /* pic_height_in_map_units_minus1 */
595 write_bits(out, &bits, 1, 1); /* frame_mbs_only_flag */
596 write_bits(out, &bits, 1, 1); /* direct_8x8_frame_field_flag */
597 write_bits(out, &bits, 0, 1); /* frame_cropping_flag */
598 write_bits(out, &bits, 0, 1); /* vui_parameters_present_flag */
599 write_h264_end(out, &bits, 0);
600
601 write_bytes(out, &bits, pps, sizeof(pps));
602 write_ue(out, &bits, 0); /* pic_parameter_set_id */
603 write_ue(out, &bits, 0); /* seq_parameter_set_id */
604 write_bits(out, &bits, 0, 1); /* entropy_coding_mode_flag */
605 write_bits(out, &bits, 0, 1); /* bottom_field_pic_order_in_frame_present_flag */
606 write_ue(out, &bits, 0); /* num_slice_groups_minus1 */
607 write_ue(out, &bits, 0); /* num_ref_idx_l0_default_active_minus1 */
608 write_ue(out, &bits, 0); /* num_ref_idx_l1_default_active_minus1 */
609 write_bits(out, &bits, 0, 1); /* weighted_pred_flag */
610 write_bits(out, &bits, 0, 2); /* weighted_bipred_idc */
611 write_se(out, &bits, 0); /* pic_init_qp_minus26 */
612 write_se(out, &bits, 0); /* pic_init_qs_minus26 */
613 write_se(out, &bits, 2); /* chroma_qp_index_offset */
614 write_bits(out, &bits, 0, 1); /* deblocking_filter_control_present_flag */
615 write_bits(out, &bits, 1, 1); /* constrained_intra_pred_flag */
616 write_bits(out, &bits, 0, 1); /* redundant_pic_cnt_present_flag */
617 write_h264_end(out, &bits, 1);
618} 578}
619 579
620static int solo_fill_mpeg(struct solo_enc_fh *fh, struct solo_enc_buf *enc_buf, 580static int solo_fill_mpeg(struct solo_enc_fh *fh, struct videobuf_buffer *vb,
621 struct videobuf_buffer *vb, 581 struct videobuf_dmabuf *vbuf, struct vop_header *vh)
622 struct videobuf_dmabuf *vbuf)
623{ 582{
624 struct solo_enc_dev *solo_enc = fh->enc; 583 struct solo_enc_dev *solo_enc = fh->enc;
625 struct solo_dev *solo_dev = solo_enc->solo_dev; 584 struct solo_dev *solo_dev = solo_enc->solo_dev;
626 585 struct solo_videobuf *svb = (struct solo_videobuf *)vb;
627#define VH_WORDS 16 586 int frame_off, frame_size;
628#define MAX_VOL_HEADER_LENGTH 64
629
630 __le32 vh[VH_WORDS];
631 int ret;
632 int frame_size, frame_off;
633 int skip = 0; 587 int skip = 0;
634 588
635 if (WARN_ON_ONCE(enc_buf->size <= sizeof(vh))) 589 if (vb->bsize < vh->mpeg_size)
636 return -EINVAL; 590 return -EIO;
637
638 /* First get the hardware vop header (not real mpeg) */
639 ret = enc_get_mpeg_dma(solo_dev, vh, enc_buf->off, sizeof(vh));
640 if (WARN_ON_ONCE(ret))
641 return ret;
642 591
643 if (WARN_ON_ONCE(vop_size(vh) > enc_buf->size)) 592 vb->width = vh->hsize << 4;
644 return -EINVAL; 593 vb->height = vh->vsize << 4;
594 vb->size = vh->mpeg_size;
645 595
646 vb->width = vop_hsize(vh) << 4; 596 /* If this is a key frame, add extra header */
647 vb->height = vop_vsize(vh) << 4; 597 if (!vh->vop_type) {
648 vb->size = vop_size(vh); 598 sg_copy_from_buffer(vbuf->sglist, vbuf->sglen,
599 solo_enc->vop,
600 solo_enc->vop_len);
649 601
650 /* If this is a key frame, add extra m4v header */ 602 skip = solo_enc->vop_len;
651 if (!enc_buf->vop) { 603 vb->size += solo_enc->vop_len;
652 u8 header[MAX_VOL_HEADER_LENGTH], *out = header;
653 604
654 if (solo_dev->flags & FLAGS_6110) 605 svb->flags |= V4L2_BUF_FLAG_KEYFRAME;
655 h264_write_vol(&out, solo_dev, vh); 606 } else {
656 else 607 svb->flags |= V4L2_BUF_FLAG_PFRAME;
657 mpeg4_write_vol(&out, solo_dev, vh,
658 solo_dev->fps * 1000,
659 solo_enc->interval * 1000);
660 skip = out - header;
661 enc_write_sg(vbuf->sglist, header, skip);
662 /* Adjust the dma buffer past this header */
663 vb->size += skip;
664 } 608 }
665 609
666 /* Now get the actual mpeg payload */ 610 /* Now get the actual mpeg payload */
667 frame_off = (enc_buf->off + sizeof(vh)) % SOLO_MP4E_EXT_SIZE(solo_dev); 611 frame_off = (vh->mpeg_off + sizeof(*vh))
668 frame_size = enc_buf->size - sizeof(vh); 612 % SOLO_MP4E_EXT_SIZE(solo_dev);
669 613 frame_size = (vh->mpeg_size + skip + (DMA_ALIGN - 1))
670 ret = enc_get_mpeg_dma_sg(solo_dev, fh->desc, vbuf->sglist, 614 & ~(DMA_ALIGN - 1);
671 skip, frame_off, frame_size);
672 WARN_ON_ONCE(ret);
673 615
674 return ret; 616 return solo_send_desc(fh, skip, vbuf, frame_off, frame_size,
617 SOLO_MP4E_EXT_ADDR(solo_dev),
618 SOLO_MP4E_EXT_SIZE(solo_dev));
675} 619}
676 620
677static void solo_enc_fillbuf(struct solo_enc_fh *fh, 621static int solo_enc_fillbuf(struct solo_enc_fh *fh,
678 struct videobuf_buffer *vb) 622 struct videobuf_buffer *vb,
623 struct solo_enc_buf *enc_buf)
679{ 624{
680 struct solo_enc_dev *solo_enc = fh->enc; 625 struct solo_enc_dev *solo_enc = fh->enc;
681 struct solo_dev *solo_dev = solo_enc->solo_dev; 626 struct solo_videobuf *svb = (struct solo_videobuf *)vb;
682 struct solo_enc_buf *enc_buf = NULL; 627 struct videobuf_dmabuf *vbuf = NULL;
683 struct videobuf_dmabuf *vbuf; 628 struct vop_header *vh = enc_buf->vh;
684 int ret; 629 int ret;
685 int error = 1;
686 u16 idx = fh->rd_idx;
687
688 while (idx != solo_dev->enc_wr_idx) {
689 struct solo_enc_buf *ebuf = &solo_dev->enc_buf[idx];
690 630
691 idx = (idx + 1) % SOLO_NR_RING_BUFS; 631 vbuf = videobuf_to_dma(vb);
692 632 if (WARN_ON_ONCE(!vbuf)) {
693 if (ebuf->ch != solo_enc->ch) 633 ret = -EIO;
694 continue; 634 goto vbuf_error;
695
696 if (fh->fmt == V4L2_PIX_FMT_MPEG) {
697 if (fh->type == ebuf->type) {
698 enc_buf = ebuf;
699 break;
700 }
701 } else {
702 /* For mjpeg, keep reading to the newest frame */
703 enc_buf = ebuf;
704 }
705 } 635 }
706 636
707 fh->rd_idx = idx; 637 /* Setup some common flags for both types */
708 638 svb->flags = V4L2_BUF_FLAG_TIMECODE;
709 if (WARN_ON_ONCE(!enc_buf)) 639 vb->ts.tv_sec = vh->sec;
710 goto buf_err; 640 vb->ts.tv_usec = vh->usec;
711 641
712 if ((fh->fmt == V4L2_PIX_FMT_MPEG && 642 /* Check for motion flags */
713 vb->bsize < enc_buf->size) || 643 if (solo_is_motion_on(solo_enc)) {
714 (fh->fmt == V4L2_PIX_FMT_MJPEG && 644 svb->flags |= V4L2_BUF_FLAG_MOTION_ON;
715 vb->bsize < (enc_buf->jpeg_size + sizeof(jpeg_header)))) { 645 if (enc_buf->motion)
716 WARN_ON_ONCE(1); 646 svb->flags |= V4L2_BUF_FLAG_MOTION_DETECTED;
717 goto buf_err;
718 } 647 }
719 648
720 vbuf = videobuf_to_dma(vb);
721 if (WARN_ON_ONCE(!vbuf))
722 goto buf_err;
723
724 if (fh->fmt == V4L2_PIX_FMT_MPEG) 649 if (fh->fmt == V4L2_PIX_FMT_MPEG)
725 ret = solo_fill_mpeg(fh, enc_buf, vb, vbuf); 650 ret = solo_fill_mpeg(fh, vb, vbuf, vh);
726 else 651 else
727 ret = solo_fill_jpeg(fh, enc_buf, vb, vbuf); 652 ret = solo_fill_jpeg(fh, vb, vbuf, vh);
728 653
729 if (!ret) 654vbuf_error:
730 error = 0; 655 /* On error, we push this buffer back into the queue. The
656 * videobuf-core doesn't handle error packets very well. Plus
657 * we recover nicely internally anyway. */
658 if (ret) {
659 unsigned long flags;
731 660
732buf_err: 661 spin_lock_irqsave(&fh->av_lock, flags);
733 if (error) { 662 list_add(&vb->queue, &fh->vidq_active);
734 vb->state = VIDEOBUF_ERROR; 663 vb->state = VIDEOBUF_QUEUED;
664 spin_unlock_irqrestore(&fh->av_lock, flags);
735 } else { 665 } else {
736 vb->field_count++;
737 vb->ts = enc_buf->ts;
738 vb->state = VIDEOBUF_DONE; 666 vb->state = VIDEOBUF_DONE;
739 } 667 vb->field_count++;
668 vb->width = solo_enc->width;
669 vb->height = solo_enc->height;
740 670
741 wake_up(&vb->done); 671 wake_up(&vb->done);
672 }
742 673
743 return; 674 return ret;
744} 675}
745 676
746static void solo_enc_thread_try(struct solo_enc_fh *fh) 677static void solo_enc_handle_one(struct solo_enc_dev *solo_enc,
678 struct solo_enc_buf *enc_buf)
747{ 679{
748 struct solo_enc_dev *solo_enc = fh->enc; 680 struct solo_enc_fh *fh;
749 struct solo_dev *solo_dev = solo_enc->solo_dev;
750 struct videobuf_buffer *vb;
751 681
752 for (;;) { 682 mutex_lock(&solo_enc->enable_lock);
753 spin_lock(&solo_enc->lock); 683
684 list_for_each_entry(fh, &solo_enc->listeners, list) {
685 struct videobuf_buffer *vb;
686 unsigned long flags;
687
688 if (fh->type != enc_buf->type)
689 continue;
754 690
755 if (fh->rd_idx == solo_dev->enc_wr_idx)
756 break;
757 691
758 if (list_empty(&fh->vidq_active)) 692 if (list_empty(&fh->vidq_active))
759 break; 693 continue;
694
695 spin_lock_irqsave(&fh->av_lock, flags);
760 696
761 vb = list_first_entry(&fh->vidq_active, 697 vb = list_first_entry(&fh->vidq_active,
762 struct videobuf_buffer, queue); 698 struct videobuf_buffer, queue);
763 699
764 if (!waitqueue_active(&vb->done))
765 break;
766
767 list_del(&vb->queue); 700 list_del(&vb->queue);
701 vb->state = VIDEOBUF_ACTIVE;
768 702
769 spin_unlock(&solo_enc->lock); 703 spin_unlock_irqrestore(&fh->av_lock, flags);
770
771 solo_enc_fillbuf(fh, vb);
772 }
773
774 assert_spin_locked(&solo_enc->lock);
775 spin_unlock(&solo_enc->lock);
776}
777
778static int solo_enc_thread(void *data)
779{
780 struct solo_enc_fh *fh = data;
781 struct solo_enc_dev *solo_enc = fh->enc;
782 DECLARE_WAITQUEUE(wait, current);
783 704
784 set_freezable(); 705 solo_enc_fillbuf(fh, vb, enc_buf);
785 add_wait_queue(&solo_enc->thread_wait, &wait);
786
787 for (;;) {
788 long timeout = schedule_timeout_interruptible(HZ);
789 if (timeout == -ERESTARTSYS || kthread_should_stop())
790 break;
791 solo_enc_thread_try(fh);
792 try_to_freeze();
793 } 706 }
794 707
795 remove_wait_queue(&solo_enc->thread_wait, &wait); 708 mutex_unlock(&solo_enc->enable_lock);
796
797 return 0;
798} 709}
799 710
800void solo_motion_isr(struct solo_dev *solo_dev) 711void solo_enc_v4l2_isr(struct solo_dev *solo_dev)
801{ 712{
802 u32 status; 713 wake_up_interruptible_all(&solo_dev->ring_thread_wait);
803 int i;
804
805 solo_reg_write(solo_dev, SOLO_IRQ_STAT, SOLO_IRQ_MOTION);
806
807 status = solo_reg_read(solo_dev, SOLO_VI_MOT_STATUS);
808
809 for (i = 0; i < solo_dev->nr_chans; i++) {
810 struct solo_enc_dev *solo_enc = solo_dev->v4l2_enc[i];
811
812 BUG_ON(solo_enc == NULL);
813
814 if (solo_enc->motion_detected)
815 continue;
816 if (!(status & (1 << i)))
817 continue;
818
819 solo_enc->motion_detected = 1;
820 }
821} 714}
822 715
823void solo_enc_v4l2_isr(struct solo_dev *solo_dev) 716static void solo_handle_ring(struct solo_dev *solo_dev)
824{ 717{
825 struct solo_enc_buf *enc_buf; 718 for (;;) {
826 u32 mpeg_current, mpeg_next, mpeg_size; 719 struct solo_enc_dev *solo_enc;
827 u32 jpeg_current, jpeg_next, jpeg_size; 720 struct solo_enc_buf enc_buf;
828 u32 reg_mpeg_size; 721 u32 mpeg_current, off;
829 u8 cur_q, vop_type; 722 u8 ch;
830 u8 ch; 723 u8 cur_q;
831 enum solo_enc_types enc_type; 724
832 725 /* Check if the hardware has any new ones in the queue */
833 solo_reg_write(solo_dev, SOLO_IRQ_STAT, SOLO_IRQ_ENCODER); 726 cur_q = solo_reg_read(solo_dev, SOLO_VE_STATE(11)) & 0xff;
834 727 if (cur_q == solo_dev->enc_idx)
835 cur_q = ((solo_reg_read(solo_dev, SOLO_VE_STATE(11)) & 0xF) + 1) % MP4_QS; 728 break;
836
837 reg_mpeg_size = ((solo_reg_read(solo_dev, SOLO_VE_STATE(0)) & 0xFFFFF) + 64 + 8) & ~7;
838 729
839 while (solo_dev->enc_idx != cur_q) {
840 mpeg_current = solo_reg_read(solo_dev, 730 mpeg_current = solo_reg_read(solo_dev,
841 SOLO_VE_MPEG4_QUE(solo_dev->enc_idx)); 731 SOLO_VE_MPEG4_QUE(solo_dev->enc_idx));
842 jpeg_current = solo_reg_read(solo_dev,
843 SOLO_VE_JPEG_QUE(solo_dev->enc_idx));
844 solo_dev->enc_idx = (solo_dev->enc_idx + 1) % MP4_QS; 732 solo_dev->enc_idx = (solo_dev->enc_idx + 1) % MP4_QS;
845 mpeg_next = solo_reg_read(solo_dev,
846 SOLO_VE_MPEG4_QUE(solo_dev->enc_idx));
847 jpeg_next = solo_reg_read(solo_dev,
848 SOLO_VE_JPEG_QUE(solo_dev->enc_idx));
849 733
850 ch = (mpeg_current >> 24) & 0x1f; 734 ch = (mpeg_current >> 24) & 0x1f;
735 off = mpeg_current & 0x00ffffff;
736
851 if (ch >= SOLO_MAX_CHANNELS) { 737 if (ch >= SOLO_MAX_CHANNELS) {
852 ch -= SOLO_MAX_CHANNELS; 738 ch -= SOLO_MAX_CHANNELS;
853 enc_type = SOLO_ENC_TYPE_EXT; 739 enc_buf.type = SOLO_ENC_TYPE_EXT;
854 } else 740 } else
855 enc_type = SOLO_ENC_TYPE_STD; 741 enc_buf.type = SOLO_ENC_TYPE_STD;
856
857 vop_type = (mpeg_current >> 29) & 3;
858
859 mpeg_current &= 0x00ffffff;
860 mpeg_next &= 0x00ffffff;
861 jpeg_current &= 0x00ffffff;
862 jpeg_next &= 0x00ffffff;
863
864 mpeg_size = (SOLO_MP4E_EXT_SIZE(solo_dev) +
865 mpeg_next - mpeg_current) %
866 SOLO_MP4E_EXT_SIZE(solo_dev);
867
868 jpeg_size = (SOLO_JPEG_EXT_SIZE(solo_dev) +
869 jpeg_next - jpeg_current) %
870 SOLO_JPEG_EXT_SIZE(solo_dev);
871 742
872 /* XXX I think this means we had a ring overflow? */ 743 solo_enc = solo_dev->v4l2_enc[ch];
873 if (mpeg_current > mpeg_next && mpeg_size != reg_mpeg_size) { 744 if (solo_enc == NULL) {
874 enc_reset_gop(solo_dev, ch); 745 dev_err(&solo_dev->pdev->dev,
746 "Got spurious packet for channel %d\n", ch);
875 continue; 747 continue;
876 } 748 }
877 749
878 /* When resetting the GOP, skip frames until I-frame */ 750 /* FAIL... */
879 if (enc_gop_reset(solo_dev, ch, vop_type)) 751 if (enc_get_mpeg_dma(solo_dev, solo_dev->vh_dma, off,
752 sizeof(struct vop_header)))
880 continue; 753 continue;
881 754
882 enc_buf = &solo_dev->enc_buf[solo_dev->enc_wr_idx]; 755 enc_buf.vh = (struct vop_header *)solo_dev->vh_buf;
756 enc_buf.vh->mpeg_off -= SOLO_MP4E_EXT_ADDR(solo_dev);
757 enc_buf.vh->jpeg_off -= SOLO_JPEG_EXT_ADDR(solo_dev);
883 758
884 enc_buf->vop = vop_type; 759 /* Sanity check */
885 enc_buf->ch = ch; 760 if (enc_buf.vh->mpeg_off != off)
886 enc_buf->off = mpeg_current; 761 continue;
887 enc_buf->size = mpeg_size; 762
888 enc_buf->jpeg_off = jpeg_current; 763 if (solo_motion_detected(solo_enc))
889 enc_buf->jpeg_size = jpeg_size; 764 enc_buf.motion = 1;
890 enc_buf->type = enc_type; 765 else
766 enc_buf.motion = 0;
767
768 solo_enc_handle_one(solo_enc, &enc_buf);
769 }
770}
891 771
892 do_gettimeofday(&enc_buf->ts); 772static int solo_ring_thread(void *data)
773{
774 struct solo_dev *solo_dev = data;
775 DECLARE_WAITQUEUE(wait, current);
893 776
894 solo_dev->enc_wr_idx = (solo_dev->enc_wr_idx + 1) % 777 set_freezable();
895 SOLO_NR_RING_BUFS; 778 add_wait_queue(&solo_dev->ring_thread_wait, &wait);
896 779
897 wake_up_interruptible(&solo_dev->v4l2_enc[ch]->thread_wait); 780 for (;;) {
781 long timeout = schedule_timeout_interruptible(HZ);
782 if (timeout == -ERESTARTSYS || kthread_should_stop())
783 break;
784 solo_irq_off(solo_dev, SOLO_IRQ_ENCODER);
785 solo_handle_ring(solo_dev);
786 solo_irq_on(solo_dev, SOLO_IRQ_ENCODER);
787 try_to_freeze();
898 } 788 }
899 789
900 return; 790 remove_wait_queue(&solo_dev->ring_thread_wait, &wait);
791
792 return 0;
901} 793}
902 794
903static int solo_enc_buf_setup(struct videobuf_queue *vq, unsigned int *count, 795static int solo_enc_buf_setup(struct videobuf_queue *vq, unsigned int *count,
@@ -915,17 +807,12 @@ static int solo_enc_buf_prepare(struct videobuf_queue *vq,
915 struct videobuf_buffer *vb, 807 struct videobuf_buffer *vb,
916 enum v4l2_field field) 808 enum v4l2_field field)
917{ 809{
918 struct solo_enc_fh *fh = vq->priv_data;
919 struct solo_enc_dev *solo_enc = fh->enc;
920
921 vb->size = FRAME_BUF_SIZE; 810 vb->size = FRAME_BUF_SIZE;
922 if (vb->baddr != 0 && vb->bsize < vb->size) 811 if (vb->baddr != 0 && vb->bsize < vb->size)
923 return -EINVAL; 812 return -EINVAL;
924 813
925 /* These properties only change when queue is idle */ 814 /* This property only change when queue is idle */
926 vb->width = solo_enc->width; 815 vb->field = field;
927 vb->height = solo_enc->height;
928 vb->field = field;
929 816
930 if (vb->state == VIDEOBUF_NEEDS_INIT) { 817 if (vb->state == VIDEOBUF_NEEDS_INIT) {
931 int rc = videobuf_iolock(vq, vb, NULL); 818 int rc = videobuf_iolock(vq, vb, NULL);
@@ -933,7 +820,7 @@ static int solo_enc_buf_prepare(struct videobuf_queue *vq,
933 struct videobuf_dmabuf *dma = videobuf_to_dma(vb); 820 struct videobuf_dmabuf *dma = videobuf_to_dma(vb);
934 videobuf_dma_unmap(vq->dev, dma); 821 videobuf_dma_unmap(vq->dev, dma);
935 videobuf_dma_free(dma); 822 videobuf_dma_free(dma);
936 vb->state = VIDEOBUF_NEEDS_INIT; 823
937 return rc; 824 return rc;
938 } 825 }
939 } 826 }
@@ -949,20 +836,18 @@ static void solo_enc_buf_queue(struct videobuf_queue *vq,
949 836
950 vb->state = VIDEOBUF_QUEUED; 837 vb->state = VIDEOBUF_QUEUED;
951 list_add_tail(&vb->queue, &fh->vidq_active); 838 list_add_tail(&vb->queue, &fh->vidq_active);
952 wake_up_interruptible(&fh->enc->thread_wait);
953} 839}
954 840
955static void solo_enc_buf_release(struct videobuf_queue *vq, 841static void solo_enc_buf_release(struct videobuf_queue *vq,
956 struct videobuf_buffer *vb) 842 struct videobuf_buffer *vb)
957{ 843{
958 struct videobuf_dmabuf *dma = videobuf_to_dma(vb); 844 struct videobuf_dmabuf *dma = videobuf_to_dma(vb);
959
960 videobuf_dma_unmap(vq->dev, dma); 845 videobuf_dma_unmap(vq->dev, dma);
961 videobuf_dma_free(dma); 846 videobuf_dma_free(dma);
962 vb->state = VIDEOBUF_NEEDS_INIT; 847 vb->state = VIDEOBUF_NEEDS_INIT;
963} 848}
964 849
965static struct videobuf_queue_ops solo_enc_video_qops = { 850static const struct videobuf_queue_ops solo_enc_video_qops = {
966 .buf_setup = solo_enc_buf_setup, 851 .buf_setup = solo_enc_buf_setup,
967 .buf_prepare = solo_enc_buf_prepare, 852 .buf_prepare = solo_enc_buf_prepare,
968 .buf_queue = solo_enc_buf_queue, 853 .buf_queue = solo_enc_buf_queue,
@@ -984,27 +869,78 @@ static int solo_enc_mmap(struct file *file, struct vm_area_struct *vma)
984 return videobuf_mmap_mapper(&fh->vidq, vma); 869 return videobuf_mmap_mapper(&fh->vidq, vma);
985} 870}
986 871
872static int solo_ring_start(struct solo_dev *solo_dev)
873{
874 if (atomic_inc_return(&solo_dev->enc_users) > 1)
875 return 0;
876
877 solo_dev->ring_thread = kthread_run(solo_ring_thread, solo_dev,
878 SOLO6X10_NAME "_ring");
879 if (IS_ERR(solo_dev->ring_thread)) {
880 int err = PTR_ERR(solo_dev->ring_thread);
881 solo_dev->ring_thread = NULL;
882 return err;
883 }
884
885 solo_irq_on(solo_dev, SOLO_IRQ_ENCODER);
886
887 return 0;
888}
889
890static void solo_ring_stop(struct solo_dev *solo_dev)
891{
892 if (atomic_dec_return(&solo_dev->enc_users) > 0)
893 return;
894
895 if (solo_dev->ring_thread) {
896 kthread_stop(solo_dev->ring_thread);
897 solo_dev->ring_thread = NULL;
898 }
899
900 solo_irq_off(solo_dev, SOLO_IRQ_ENCODER);
901}
902
987static int solo_enc_open(struct file *file) 903static int solo_enc_open(struct file *file)
988{ 904{
989 struct solo_enc_dev *solo_enc = video_drvdata(file); 905 struct solo_enc_dev *solo_enc = video_drvdata(file);
906 struct solo_dev *solo_dev = solo_enc->solo_dev;
990 struct solo_enc_fh *fh; 907 struct solo_enc_fh *fh;
908 int ret;
909
910 ret = solo_ring_start(solo_dev);
911 if (ret)
912 return ret;
991 913
992 fh = kzalloc(sizeof(*fh), GFP_KERNEL); 914 fh = kzalloc(sizeof(*fh), GFP_KERNEL);
993 if (fh == NULL) 915 if (fh == NULL) {
916 solo_ring_stop(solo_dev);
917 return -ENOMEM;
918 }
919
920 fh->desc_nelts = 32;
921 fh->desc_items = pci_alloc_consistent(solo_dev->pdev,
922 sizeof(struct solo_p2m_desc) *
923 fh->desc_nelts, &fh->desc_dma);
924 if (fh->desc_items == NULL) {
925 kfree(fh);
926 solo_ring_stop(solo_dev);
994 return -ENOMEM; 927 return -ENOMEM;
928 }
995 929
996 fh->enc = solo_enc; 930 fh->enc = solo_enc;
931 spin_lock_init(&fh->av_lock);
997 file->private_data = fh; 932 file->private_data = fh;
998 INIT_LIST_HEAD(&fh->vidq_active); 933 INIT_LIST_HEAD(&fh->vidq_active);
999 fh->fmt = V4L2_PIX_FMT_MPEG; 934 fh->fmt = V4L2_PIX_FMT_MPEG;
1000 fh->type = SOLO_ENC_TYPE_STD; 935 fh->type = SOLO_ENC_TYPE_STD;
1001 936
1002 videobuf_queue_sg_init(&fh->vidq, &solo_enc_video_qops, 937 videobuf_queue_sg_init(&fh->vidq, &solo_enc_video_qops,
1003 &solo_enc->solo_dev->pdev->dev, 938 &solo_dev->pdev->dev,
1004 &solo_enc->lock, 939 &fh->av_lock,
1005 V4L2_BUF_TYPE_VIDEO_CAPTURE, 940 V4L2_BUF_TYPE_VIDEO_CAPTURE,
1006 V4L2_FIELD_INTERLACED, 941 V4L2_FIELD_INTERLACED,
1007 sizeof(struct videobuf_buffer), fh, NULL); 942 sizeof(struct solo_videobuf),
943 fh, NULL);
1008 944
1009 return 0; 945 return 0;
1010} 946}
@@ -1013,22 +949,12 @@ static ssize_t solo_enc_read(struct file *file, char __user *data,
1013 size_t count, loff_t *ppos) 949 size_t count, loff_t *ppos)
1014{ 950{
1015 struct solo_enc_fh *fh = file->private_data; 951 struct solo_enc_fh *fh = file->private_data;
1016 struct solo_enc_dev *solo_enc = fh->enc; 952 int ret;
1017 953
1018 /* Make sure the encoder is on */ 954 /* Make sure the encoder is on */
1019 if (!fh->enc_on) { 955 ret = solo_enc_on(fh);
1020 int ret; 956 if (ret)
1021 957 return ret;
1022 spin_lock(&solo_enc->lock);
1023 ret = solo_enc_on(fh);
1024 spin_unlock(&solo_enc->lock);
1025 if (ret)
1026 return ret;
1027
1028 ret = solo_start_fh_thread(fh);
1029 if (ret)
1030 return ret;
1031 }
1032 958
1033 return videobuf_read_stream(&fh->vidq, data, count, ppos, 0, 959 return videobuf_read_stream(&fh->vidq, data, count, ppos, 0,
1034 file->f_flags & O_NONBLOCK); 960 file->f_flags & O_NONBLOCK);
@@ -1037,17 +963,21 @@ static ssize_t solo_enc_read(struct file *file, char __user *data,
1037static int solo_enc_release(struct file *file) 963static int solo_enc_release(struct file *file)
1038{ 964{
1039 struct solo_enc_fh *fh = file->private_data; 965 struct solo_enc_fh *fh = file->private_data;
1040 struct solo_enc_dev *solo_enc = fh->enc; 966 struct solo_dev *solo_dev = fh->enc->solo_dev;
967
968 solo_enc_off(fh);
1041 969
1042 videobuf_stop(&fh->vidq); 970 videobuf_stop(&fh->vidq);
1043 videobuf_mmap_free(&fh->vidq); 971 videobuf_mmap_free(&fh->vidq);
1044 972
1045 spin_lock(&solo_enc->lock); 973 pci_free_consistent(fh->enc->solo_dev->pdev,
1046 solo_enc_off(fh); 974 sizeof(struct solo_p2m_desc) *
1047 spin_unlock(&solo_enc->lock); 975 fh->desc_nelts, fh->desc_items, fh->desc_dma);
1048 976
1049 kfree(fh); 977 kfree(fh);
1050 978
979 solo_ring_stop(solo_dev);
980
1051 return 0; 981 return 0;
1052} 982}
1053 983
@@ -1095,7 +1025,8 @@ static int solo_enc_enum_input(struct file *file, void *priv,
1095 return 0; 1025 return 0;
1096} 1026}
1097 1027
1098static int solo_enc_set_input(struct file *file, void *priv, unsigned int index) 1028static int solo_enc_set_input(struct file *file, void *priv,
1029 unsigned int index)
1099{ 1030{
1100 if (index) 1031 if (index)
1101 return -EINVAL; 1032 return -EINVAL;
@@ -1144,8 +1075,8 @@ static int solo_enc_try_fmt_cap(struct file *file, void *priv,
1144 pix->pixelformat != V4L2_PIX_FMT_MJPEG) 1075 pix->pixelformat != V4L2_PIX_FMT_MJPEG)
1145 return -EINVAL; 1076 return -EINVAL;
1146 1077
1147 /* We cannot change width/height in mid read */ 1078 /* We cannot change width/height in mid mpeg */
1148 if (atomic_read(&solo_enc->readers) > 0) { 1079 if (atomic_read(&solo_enc->mpeg_readers) > 0) {
1149 if (pix->width != solo_enc->width || 1080 if (pix->width != solo_enc->width ||
1150 pix->height != solo_enc->height) 1081 pix->height != solo_enc->height)
1151 return -EBUSY; 1082 return -EBUSY;
@@ -1183,11 +1114,11 @@ static int solo_enc_set_fmt_cap(struct file *file, void *priv,
1183 struct v4l2_pix_format *pix = &f->fmt.pix; 1114 struct v4l2_pix_format *pix = &f->fmt.pix;
1184 int ret; 1115 int ret;
1185 1116
1186 spin_lock(&solo_enc->lock); 1117 mutex_lock(&solo_enc->enable_lock);
1187 1118
1188 ret = solo_enc_try_fmt_cap(file, priv, f); 1119 ret = solo_enc_try_fmt_cap(file, priv, f);
1189 if (ret) { 1120 if (ret) {
1190 spin_unlock(&solo_enc->lock); 1121 mutex_unlock(&solo_enc->enable_lock);
1191 return ret; 1122 return ret;
1192 } 1123 }
1193 1124
@@ -1201,14 +1132,10 @@ static int solo_enc_set_fmt_cap(struct file *file, void *priv,
1201 1132
1202 if (pix->priv) 1133 if (pix->priv)
1203 fh->type = SOLO_ENC_TYPE_EXT; 1134 fh->type = SOLO_ENC_TYPE_EXT;
1204 ret = solo_enc_on(fh);
1205
1206 spin_unlock(&solo_enc->lock);
1207 1135
1208 if (ret) 1136 mutex_unlock(&solo_enc->enable_lock);
1209 return ret;
1210 1137
1211 return solo_start_fh_thread(fh); 1138 return 0;
1212} 1139}
1213 1140
1214static int solo_enc_get_fmt_cap(struct file *file, void *priv, 1141static int solo_enc_get_fmt_cap(struct file *file, void *priv,
@@ -1245,7 +1172,8 @@ static int solo_enc_querybuf(struct file *file, void *priv,
1245 return videobuf_querybuf(&fh->vidq, buf); 1172 return videobuf_querybuf(&fh->vidq, buf);
1246} 1173}
1247 1174
1248static int solo_enc_qbuf(struct file *file, void *priv, struct v4l2_buffer *buf) 1175static int solo_enc_qbuf(struct file *file, void *priv,
1176 struct v4l2_buffer *buf)
1249{ 1177{
1250 struct solo_enc_fh *fh = priv; 1178 struct solo_enc_fh *fh = priv;
1251 1179
@@ -1256,50 +1184,21 @@ static int solo_enc_dqbuf(struct file *file, void *priv,
1256 struct v4l2_buffer *buf) 1184 struct v4l2_buffer *buf)
1257{ 1185{
1258 struct solo_enc_fh *fh = priv; 1186 struct solo_enc_fh *fh = priv;
1259 struct solo_enc_dev *solo_enc = fh->enc; 1187 struct solo_videobuf *svb;
1260 int ret; 1188 int ret;
1261 1189
1262 /* Make sure the encoder is on */ 1190 /* Make sure the encoder is on */
1263 if (!fh->enc_on) { 1191 ret = solo_enc_on(fh);
1264 spin_lock(&solo_enc->lock); 1192 if (ret)
1265 ret = solo_enc_on(fh); 1193 return ret;
1266 spin_unlock(&solo_enc->lock);
1267 if (ret)
1268 return ret;
1269
1270 ret = solo_start_fh_thread(fh);
1271 if (ret)
1272 return ret;
1273 }
1274 1194
1275 ret = videobuf_dqbuf(&fh->vidq, buf, file->f_flags & O_NONBLOCK); 1195 ret = videobuf_dqbuf(&fh->vidq, buf, file->f_flags & O_NONBLOCK);
1276 if (ret) 1196 if (ret)
1277 return ret; 1197 return ret;
1278 1198
1279 /* Signal motion detection */ 1199 /* Copy over the flags */
1280 if (solo_is_motion_on(solo_enc)) { 1200 svb = (struct solo_videobuf *)fh->vidq.bufs[buf->index];
1281 buf->flags |= V4L2_BUF_FLAG_MOTION_ON; 1201 buf->flags |= svb->flags;
1282 if (solo_enc->motion_detected) {
1283 buf->flags |= V4L2_BUF_FLAG_MOTION_DETECTED;
1284 solo_reg_write(solo_enc->solo_dev, SOLO_VI_MOT_CLEAR,
1285 1 << solo_enc->ch);
1286 solo_enc->motion_detected = 0;
1287 }
1288 }
1289
1290 /* Check for key frame on mpeg data */
1291 if (fh->fmt == V4L2_PIX_FMT_MPEG) {
1292 struct videobuf_dmabuf *vbuf =
1293 videobuf_to_dma(fh->vidq.bufs[buf->index]);
1294
1295 if (vbuf) {
1296 u8 *p = sg_virt(vbuf->sglist);
1297 if (p[3] == 0x00)
1298 buf->flags |= V4L2_BUF_FLAG_KEYFRAME;
1299 else
1300 buf->flags |= V4L2_BUF_FLAG_PFRAME;
1301 }
1302 }
1303 1202
1304 return 0; 1203 return 0;
1305} 1204}
@@ -1319,11 +1218,16 @@ static int solo_enc_streamoff(struct file *file, void *priv,
1319 enum v4l2_buf_type i) 1218 enum v4l2_buf_type i)
1320{ 1219{
1321 struct solo_enc_fh *fh = priv; 1220 struct solo_enc_fh *fh = priv;
1221 int ret;
1322 1222
1323 if (i != V4L2_BUF_TYPE_VIDEO_CAPTURE) 1223 if (i != V4L2_BUF_TYPE_VIDEO_CAPTURE)
1324 return -EINVAL; 1224 return -EINVAL;
1325 1225
1326 return videobuf_streamoff(&fh->vidq); 1226 ret = videobuf_streamoff(&fh->vidq);
1227 if (!ret)
1228 solo_enc_off(fh);
1229
1230 return ret;
1327} 1231}
1328 1232
1329static int solo_enc_s_std(struct file *file, void *priv, v4l2_std_id i) 1233static int solo_enc_s_std(struct file *file, void *priv, v4l2_std_id i)
@@ -1407,10 +1311,10 @@ static int solo_s_parm(struct file *file, void *priv,
1407 struct solo_dev *solo_dev = solo_enc->solo_dev; 1311 struct solo_dev *solo_dev = solo_enc->solo_dev;
1408 struct v4l2_captureparm *cp = &sp->parm.capture; 1312 struct v4l2_captureparm *cp = &sp->parm.capture;
1409 1313
1410 spin_lock(&solo_enc->lock); 1314 mutex_lock(&solo_enc->enable_lock);
1411 1315
1412 if (atomic_read(&solo_enc->readers) > 0) { 1316 if (atomic_read(&solo_enc->mpeg_readers) > 0) {
1413 spin_unlock(&solo_enc->lock); 1317 mutex_unlock(&solo_enc->enable_lock);
1414 return -EBUSY; 1318 return -EBUSY;
1415 } 1319 }
1416 1320
@@ -1431,10 +1335,9 @@ static int solo_s_parm(struct file *file, void *priv,
1431 1335
1432 cp->capability = V4L2_CAP_TIMEPERFRAME; 1336 cp->capability = V4L2_CAP_TIMEPERFRAME;
1433 1337
1434 solo_enc->gop = max(solo_dev->fps / solo_enc->interval, 1);
1435 solo_update_mode(solo_enc); 1338 solo_update_mode(solo_enc);
1436 1339
1437 spin_unlock(&solo_enc->lock); 1340 mutex_unlock(&solo_enc->enable_lock);
1438 1341
1439 return 0; 1342 return 0;
1440} 1343}
@@ -1510,6 +1413,7 @@ static int solo_querymenu(struct file *file, void *priv,
1510 int err; 1413 int err;
1511 1414
1512 qctrl.id = qmenu->id; 1415 qctrl.id = qmenu->id;
1416
1513 err = solo_queryctrl(file, priv, &qctrl); 1417 err = solo_queryctrl(file, priv, &qctrl);
1514 if (err) 1418 if (err)
1515 return err; 1419 return err;
@@ -1536,6 +1440,8 @@ static int solo_g_ctrl(struct file *file, void *priv,
1536 ctrl->value = V4L2_MPEG_VIDEO_ENCODING_MPEG_4_AVC; 1440 ctrl->value = V4L2_MPEG_VIDEO_ENCODING_MPEG_4_AVC;
1537 break; 1441 break;
1538 case V4L2_CID_MPEG_VIDEO_GOP_SIZE: 1442 case V4L2_CID_MPEG_VIDEO_GOP_SIZE:
1443 if (atomic_read(&solo_enc->readers) > 0)
1444 return -EBUSY;
1539 ctrl->value = solo_enc->gop; 1445 ctrl->value = solo_enc->gop;
1540 break; 1446 break;
1541 case V4L2_CID_MOTION_THRESHOLD: 1447 case V4L2_CID_MOTION_THRESHOLD:
@@ -1574,19 +1480,32 @@ static int solo_s_ctrl(struct file *file, void *priv,
1574 if (ctrl->value < 1 || ctrl->value > 255) 1480 if (ctrl->value < 1 || ctrl->value > 255)
1575 return -ERANGE; 1481 return -ERANGE;
1576 solo_enc->gop = ctrl->value; 1482 solo_enc->gop = ctrl->value;
1577 solo_reg_write(solo_dev, SOLO_VE_CH_GOP(solo_enc->ch),
1578 solo_enc->gop);
1579 solo_reg_write(solo_dev, SOLO_VE_CH_GOP_E(solo_enc->ch),
1580 solo_enc->gop);
1581 break; 1483 break;
1582 case V4L2_CID_MOTION_THRESHOLD: 1484 case V4L2_CID_MOTION_THRESHOLD:
1583 /* TODO accept value on lower 16-bits and use high 1485 {
1584 * 16-bits to assign the value to a specific block */ 1486 u16 block = (ctrl->value >> 16) & 0xffff;
1585 if (ctrl->value < 0 || ctrl->value > 0xffff) 1487 u16 value = ctrl->value & 0xffff;
1488
1489 /* Motion thresholds are in a table of 64x64 samples, with
1490 * each sample representing 16x16 pixels of the source. In
1491 * effect, 44x30 samples are used for NTSC, and 44x36 for PAL.
1492 * The 5th sample on the 10th row is (10*64)+5 = 645.
1493 *
1494 * Block is 0 to set the threshold globally, or any positive
1495 * number under 2049 to set block-1 individually. */
1496 if (block > 2049)
1586 return -ERANGE; 1497 return -ERANGE;
1587 solo_enc->motion_thresh = ctrl->value; 1498
1588 solo_set_motion_threshold(solo_dev, solo_enc->ch, ctrl->value); 1499 if (block == 0) {
1500 solo_enc->motion_thresh = value;
1501 return solo_set_motion_threshold(solo_dev,
1502 solo_enc->ch, value);
1503 } else {
1504 return solo_set_motion_block(solo_dev, solo_enc->ch,
1505 value, block - 1);
1506 }
1589 break; 1507 break;
1508 }
1590 case V4L2_CID_MOTION_ENABLE: 1509 case V4L2_CID_MOTION_ENABLE:
1591 solo_motion_toggle(solo_enc, ctrl->value); 1510 solo_motion_toggle(solo_enc, ctrl->value);
1592 break; 1511 break;
@@ -1613,6 +1532,7 @@ static int solo_s_ext_ctrls(struct file *file, void *priv,
1613 if (ctrl->size - 1 > OSD_TEXT_MAX) 1532 if (ctrl->size - 1 > OSD_TEXT_MAX)
1614 err = -ERANGE; 1533 err = -ERANGE;
1615 else { 1534 else {
1535 mutex_lock(&solo_enc->enable_lock);
1616 err = copy_from_user(solo_enc->osd_text, 1536 err = copy_from_user(solo_enc->osd_text,
1617 ctrl->string, 1537 ctrl->string,
1618 OSD_TEXT_MAX); 1538 OSD_TEXT_MAX);
@@ -1621,6 +1541,7 @@ static int solo_s_ext_ctrls(struct file *file, void *priv,
1621 err = solo_osd_print(solo_enc); 1541 err = solo_osd_print(solo_enc);
1622 else 1542 else
1623 err = -EFAULT; 1543 err = -EFAULT;
1544 mutex_unlock(&solo_enc->enable_lock);
1624 } 1545 }
1625 break; 1546 break;
1626 default: 1547 default:
@@ -1653,11 +1574,13 @@ static int solo_g_ext_ctrls(struct file *file, void *priv,
1653 ctrl->size = OSD_TEXT_MAX; 1574 ctrl->size = OSD_TEXT_MAX;
1654 err = -ENOSPC; 1575 err = -ENOSPC;
1655 } else { 1576 } else {
1577 mutex_lock(&solo_enc->enable_lock);
1656 err = copy_to_user(ctrl->string, 1578 err = copy_to_user(ctrl->string,
1657 solo_enc->osd_text, 1579 solo_enc->osd_text,
1658 OSD_TEXT_MAX); 1580 OSD_TEXT_MAX);
1659 if (err) 1581 if (err)
1660 err = -EFAULT; 1582 err = -EFAULT;
1583 mutex_unlock(&solo_enc->enable_lock);
1661 } 1584 }
1662 break; 1585 break;
1663 default: 1586 default:
@@ -1717,7 +1640,7 @@ static const struct v4l2_ioctl_ops solo_enc_ioctl_ops = {
1717 .vidioc_s_ext_ctrls = solo_s_ext_ctrls, 1640 .vidioc_s_ext_ctrls = solo_s_ext_ctrls,
1718}; 1641};
1719 1642
1720static struct video_device solo_enc_template = { 1643static const struct video_device solo_enc_template = {
1721 .name = SOLO6X10_NAME, 1644 .name = SOLO6X10_NAME,
1722 .fops = &solo_enc_fops, 1645 .fops = &solo_enc_fops,
1723 .ioctl_ops = &solo_enc_ioctl_ops, 1646 .ioctl_ops = &solo_enc_ioctl_ops,
@@ -1728,7 +1651,8 @@ static struct video_device solo_enc_template = {
1728 .current_norm = V4L2_STD_NTSC_M, 1651 .current_norm = V4L2_STD_NTSC_M,
1729}; 1652};
1730 1653
1731static struct solo_enc_dev *solo_enc_alloc(struct solo_dev *solo_dev, u8 ch) 1654static struct solo_enc_dev *solo_enc_alloc(struct solo_dev *solo_dev,
1655 u8 ch, unsigned nr)
1732{ 1656{
1733 struct solo_enc_dev *solo_enc; 1657 struct solo_enc_dev *solo_enc;
1734 int ret; 1658 int ret;
@@ -1748,8 +1672,7 @@ static struct solo_enc_dev *solo_enc_alloc(struct solo_dev *solo_dev, u8 ch)
1748 1672
1749 *solo_enc->vfd = solo_enc_template; 1673 *solo_enc->vfd = solo_enc_template;
1750 solo_enc->vfd->parent = &solo_dev->pdev->dev; 1674 solo_enc->vfd->parent = &solo_dev->pdev->dev;
1751 ret = video_register_device(solo_enc->vfd, VFL_TYPE_GRABBER, 1675 ret = video_register_device(solo_enc->vfd, VFL_TYPE_GRABBER, nr);
1752 video_nr);
1753 if (ret < 0) { 1676 if (ret < 0) {
1754 video_device_release(solo_enc->vfd); 1677 video_device_release(solo_enc->vfd);
1755 kfree(solo_enc); 1678 kfree(solo_enc);
@@ -1762,12 +1685,12 @@ static struct solo_enc_dev *solo_enc_alloc(struct solo_dev *solo_dev, u8 ch)
1762 "%s-enc (%i/%i)", SOLO6X10_NAME, solo_dev->vfd->num, 1685 "%s-enc (%i/%i)", SOLO6X10_NAME, solo_dev->vfd->num,
1763 solo_enc->vfd->num); 1686 solo_enc->vfd->num);
1764 1687
1765 if (video_nr != -1) 1688 INIT_LIST_HEAD(&solo_enc->listeners);
1766 video_nr++; 1689 mutex_init(&solo_enc->enable_lock);
1690 spin_lock_init(&solo_enc->motion_lock);
1767 1691
1768 spin_lock_init(&solo_enc->lock);
1769 init_waitqueue_head(&solo_enc->thread_wait);
1770 atomic_set(&solo_enc->readers, 0); 1692 atomic_set(&solo_enc->readers, 0);
1693 atomic_set(&solo_enc->mpeg_readers, 0);
1771 1694
1772 solo_enc->qp = SOLO_DEFAULT_QP; 1695 solo_enc->qp = SOLO_DEFAULT_QP;
1773 solo_enc->gop = solo_dev->fps; 1696 solo_enc->gop = solo_dev->fps;
@@ -1775,9 +1698,13 @@ static struct solo_enc_dev *solo_enc_alloc(struct solo_dev *solo_dev, u8 ch)
1775 solo_enc->mode = SOLO_ENC_MODE_CIF; 1698 solo_enc->mode = SOLO_ENC_MODE_CIF;
1776 solo_enc->motion_thresh = SOLO_DEF_MOT_THRESH; 1699 solo_enc->motion_thresh = SOLO_DEF_MOT_THRESH;
1777 1700
1778 spin_lock(&solo_enc->lock); 1701 mutex_lock(&solo_enc->enable_lock);
1779 solo_update_mode(solo_enc); 1702 solo_update_mode(solo_enc);
1780 spin_unlock(&solo_enc->lock); 1703 mutex_unlock(&solo_enc->enable_lock);
1704
1705 /* Initialize this per encoder */
1706 solo_enc->jpeg_len = sizeof(jpeg_header);
1707 memcpy(solo_enc->jpeg_header, jpeg_header, solo_enc->jpeg_len);
1781 1708
1782 return solo_enc; 1709 return solo_enc;
1783} 1710}
@@ -1791,12 +1718,22 @@ static void solo_enc_free(struct solo_enc_dev *solo_enc)
1791 kfree(solo_enc); 1718 kfree(solo_enc);
1792} 1719}
1793 1720
1794int solo_enc_v4l2_init(struct solo_dev *solo_dev) 1721int solo_enc_v4l2_init(struct solo_dev *solo_dev, unsigned nr)
1795{ 1722{
1796 int i; 1723 int i;
1797 1724
1725 atomic_set(&solo_dev->enc_users, 0);
1726 init_waitqueue_head(&solo_dev->ring_thread_wait);
1727
1728 solo_dev->vh_size = sizeof(struct vop_header);
1729 solo_dev->vh_buf = pci_alloc_consistent(solo_dev->pdev,
1730 solo_dev->vh_size,
1731 &solo_dev->vh_dma);
1732 if (solo_dev->vh_buf == NULL)
1733 return -ENOMEM;
1734
1798 for (i = 0; i < solo_dev->nr_chans; i++) { 1735 for (i = 0; i < solo_dev->nr_chans; i++) {
1799 solo_dev->v4l2_enc[i] = solo_enc_alloc(solo_dev, i); 1736 solo_dev->v4l2_enc[i] = solo_enc_alloc(solo_dev, i, nr);
1800 if (IS_ERR(solo_dev->v4l2_enc[i])) 1737 if (IS_ERR(solo_dev->v4l2_enc[i]))
1801 break; 1738 break;
1802 } 1739 }
@@ -1805,11 +1742,15 @@ int solo_enc_v4l2_init(struct solo_dev *solo_dev)
1805 int ret = PTR_ERR(solo_dev->v4l2_enc[i]); 1742 int ret = PTR_ERR(solo_dev->v4l2_enc[i]);
1806 while (i--) 1743 while (i--)
1807 solo_enc_free(solo_dev->v4l2_enc[i]); 1744 solo_enc_free(solo_dev->v4l2_enc[i]);
1745 pci_free_consistent(solo_dev->pdev, solo_dev->vh_size,
1746 solo_dev->vh_buf, solo_dev->vh_dma);
1808 return ret; 1747 return ret;
1809 } 1748 }
1810 1749
1811 /* D1@MAX-FPS * 4 */ 1750 if (solo_dev->type == SOLO_DEV_6010)
1812 solo_dev->enc_bw_remain = solo_dev->fps * 4 * 4; 1751 solo_dev->enc_bw_remain = solo_dev->fps * 4 * 4;
1752 else
1753 solo_dev->enc_bw_remain = solo_dev->fps * 4 * 5;
1813 1754
1814 dev_info(&solo_dev->pdev->dev, "Encoders as /dev/video%d-%d\n", 1755 dev_info(&solo_dev->pdev->dev, "Encoders as /dev/video%d-%d\n",
1815 solo_dev->v4l2_enc[0]->vfd->num, 1756 solo_dev->v4l2_enc[0]->vfd->num,
@@ -1822,8 +1763,9 @@ void solo_enc_v4l2_exit(struct solo_dev *solo_dev)
1822{ 1763{
1823 int i; 1764 int i;
1824 1765
1825 solo_irq_off(solo_dev, SOLO_IRQ_MOTION);
1826
1827 for (i = 0; i < solo_dev->nr_chans; i++) 1766 for (i = 0; i < solo_dev->nr_chans; i++)
1828 solo_enc_free(solo_dev->v4l2_enc[i]); 1767 solo_enc_free(solo_dev->v4l2_enc[i]);
1768
1769 pci_free_consistent(solo_dev->pdev, solo_dev->vh_size,
1770 solo_dev->vh_buf, solo_dev->vh_dma);
1829} 1771}
diff --git a/drivers/staging/media/solo6x10/v4l2.c b/drivers/staging/media/solo6x10/v4l2.c
index 87f3c0452ca4..ba603ce1f746 100644
--- a/drivers/staging/media/solo6x10/v4l2.c
+++ b/drivers/staging/media/solo6x10/v4l2.c
@@ -1,6 +1,11 @@
1/* 1/*
2 * Copyright (C) 2010 Bluecherry, LLC www.bluecherrydvr.com 2 * Copyright (C) 2010-2013 Bluecherry, LLC <http://www.bluecherrydvr.com>
3 * Copyright (C) 2010 Ben Collins <bcollins@bluecherry.net> 3 *
4 * Original author:
5 * Ben Collins <bcollins@ubuntu.com>
6 *
7 * Additional work by:
8 * John Brooks <john.brooks@bluecherry.net>
4 * 9 *
5 * This program is free software; you can redistribute it and/or modify 10 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by 11 * it under the terms of the GNU General Public License as published by
@@ -21,47 +26,43 @@
21#include <linux/module.h> 26#include <linux/module.h>
22#include <linux/kthread.h> 27#include <linux/kthread.h>
23#include <linux/freezer.h> 28#include <linux/freezer.h>
29
24#include <media/v4l2-ioctl.h> 30#include <media/v4l2-ioctl.h>
25#include <media/v4l2-common.h> 31#include <media/v4l2-common.h>
26#include <media/videobuf-dma-sg.h> 32#include <media/videobuf-dma-contig.h>
33
27#include "solo6x10.h" 34#include "solo6x10.h"
28#include "tw28.h" 35#include "tw28.h"
29 36
30#define SOLO_HW_BPL 2048
31#define SOLO_DISP_PIX_FIELD V4L2_FIELD_INTERLACED 37#define SOLO_DISP_PIX_FIELD V4L2_FIELD_INTERLACED
32 38
33/* Image size is two fields, SOLO_HW_BPL is one horizontal line */ 39/* Image size is two fields, SOLO_HW_BPL is one horizontal line in hardware */
40#define SOLO_HW_BPL 2048
34#define solo_vlines(__solo) (__solo->video_vsize * 2) 41#define solo_vlines(__solo) (__solo->video_vsize * 2)
35#define solo_image_size(__solo) (solo_bytesperline(__solo) * \ 42#define solo_image_size(__solo) (solo_bytesperline(__solo) * \
36 solo_vlines(__solo)) 43 solo_vlines(__solo))
37#define solo_bytesperline(__solo) (__solo->video_hsize * 2) 44#define solo_bytesperline(__solo) (__solo->video_hsize * 2)
38 45
39#define MIN_VID_BUFFERS 4 46#define MIN_VID_BUFFERS 2
40 47
41/* Simple file handle */ 48/* Simple file handle */
42struct solo_filehandle { 49struct solo_filehandle {
43 struct solo_dev *solo_dev; 50 struct solo_dev *solo_dev;
44 struct videobuf_queue vidq; 51 struct videobuf_queue vidq;
45 struct task_struct *kthread; 52 struct task_struct *kthread;
46 spinlock_t slock; 53 spinlock_t slock;
47 int old_write; 54 int old_write;
48 struct list_head vidq_active; 55 struct list_head vidq_active;
49 struct p2m_desc desc[SOLO_NR_P2M_DESC];
50 int desc_idx;
51}; 56};
52 57
53unsigned video_nr = -1; 58static inline void erase_on(struct solo_dev *solo_dev)
54module_param(video_nr, uint, 0644);
55MODULE_PARM_DESC(video_nr, "videoX start number, -1 is autodetect (default)");
56
57static void erase_on(struct solo_dev *solo_dev)
58{ 59{
59 solo_reg_write(solo_dev, SOLO_VO_DISP_ERASE, SOLO_VO_DISP_ERASE_ON); 60 solo_reg_write(solo_dev, SOLO_VO_DISP_ERASE, SOLO_VO_DISP_ERASE_ON);
60 solo_dev->erasing = 1; 61 solo_dev->erasing = 1;
61 solo_dev->frame_blank = 0; 62 solo_dev->frame_blank = 0;
62} 63}
63 64
64static int erase_off(struct solo_dev *solo_dev) 65static inline int erase_off(struct solo_dev *solo_dev)
65{ 66{
66 if (!solo_dev->erasing) 67 if (!solo_dev->erasing)
67 return 0; 68 return 0;
@@ -78,8 +79,7 @@ static int erase_off(struct solo_dev *solo_dev)
78 79
79void solo_video_in_isr(struct solo_dev *solo_dev) 80void solo_video_in_isr(struct solo_dev *solo_dev)
80{ 81{
81 solo_reg_write(solo_dev, SOLO_IRQ_STAT, SOLO_IRQ_VIDEO_IN); 82 wake_up_interruptible_all(&solo_dev->disp_thread_wait);
82 wake_up_interruptible(&solo_dev->disp_thread_wait);
83} 83}
84 84
85static void solo_win_setup(struct solo_dev *solo_dev, u8 ch, 85static void solo_win_setup(struct solo_dev *solo_dev, u8 ch,
@@ -202,165 +202,61 @@ static int solo_v4l2_set_ch(struct solo_dev *solo_dev, u8 ch)
202 return 0; 202 return 0;
203} 203}
204 204
205static void disp_reset_desc(struct solo_filehandle *fh)
206{
207 /* We use desc mode, which ignores desc 0 */
208 memset(fh->desc, 0, sizeof(*fh->desc));
209 fh->desc_idx = 1;
210}
211
212static int disp_flush_descs(struct solo_filehandle *fh)
213{
214 int ret;
215
216 if (!fh->desc_idx)
217 return 0;
218
219 ret = solo_p2m_dma_desc(fh->solo_dev, SOLO_P2M_DMA_ID_DISP,
220 fh->desc, fh->desc_idx);
221 disp_reset_desc(fh);
222
223 return ret;
224}
225
226static int disp_push_desc(struct solo_filehandle *fh, dma_addr_t dma_addr,
227 u32 ext_addr, int size, int repeat, int ext_size)
228{
229 if (fh->desc_idx >= SOLO_NR_P2M_DESC) {
230 int ret = disp_flush_descs(fh);
231 if (ret)
232 return ret;
233 }
234
235 solo_p2m_push_desc(&fh->desc[fh->desc_idx], 0, dma_addr, ext_addr,
236 size, repeat, ext_size);
237 fh->desc_idx++;
238
239 return 0;
240}
241
242static void solo_fillbuf(struct solo_filehandle *fh, 205static void solo_fillbuf(struct solo_filehandle *fh,
243 struct videobuf_buffer *vb) 206 struct videobuf_buffer *vb)
244{ 207{
245 struct solo_dev *solo_dev = fh->solo_dev; 208 struct solo_dev *solo_dev = fh->solo_dev;
246 struct videobuf_dmabuf *vbuf; 209 dma_addr_t vbuf;
247 unsigned int fdma_addr; 210 unsigned int fdma_addr;
248 int error = 1; 211 int error = -1;
249 int i; 212 int i;
250 struct scatterlist *sg;
251 dma_addr_t sg_dma;
252 int sg_size_left;
253 213
254 vbuf = videobuf_to_dma(vb); 214 vbuf = videobuf_to_dma_contig(vb);
255 if (!vbuf) 215 if (!vbuf)
256 goto finish_buf; 216 goto finish_buf;
257 217
258 if (erase_off(solo_dev)) { 218 if (erase_off(solo_dev)) {
259 int i; 219 void *p = videobuf_queue_to_vaddr(&fh->vidq, vb);
260 220 int image_size = solo_image_size(solo_dev);
261 /* Just blit to the entire sg list, ignoring size */ 221 for (i = 0; i < image_size; i += 2) {
262 for_each_sg(vbuf->sglist, sg, vbuf->sglen, i) { 222 ((u8 *)p)[i] = 0x80;
263 void *p = sg_virt(sg); 223 ((u8 *)p)[i + 1] = 0x00;
264 size_t len = sg_dma_len(sg);
265
266 for (i = 0; i < len; i += 2) {
267 ((u8 *)p)[i] = 0x80;
268 ((u8 *)p)[i + 1] = 0x00;
269 }
270 } 224 }
271
272 error = 0; 225 error = 0;
273 goto finish_buf; 226 } else {
274 } 227 fdma_addr = SOLO_DISP_EXT_ADDR + (fh->old_write *
275 228 (SOLO_HW_BPL * solo_vlines(solo_dev)));
276 disp_reset_desc(fh);
277 sg = vbuf->sglist;
278 sg_dma = sg_dma_address(sg);
279 sg_size_left = sg_dma_len(sg);
280
281 fdma_addr = SOLO_DISP_EXT_ADDR + (fh->old_write *
282 (SOLO_HW_BPL * solo_vlines(solo_dev)));
283
284 for (i = 0; i < solo_vlines(solo_dev); i++) {
285 int line_len = solo_bytesperline(solo_dev);
286 int lines;
287
288 if (!sg_size_left) {
289 sg = sg_next(sg);
290 if (sg == NULL)
291 goto finish_buf;
292 sg_dma = sg_dma_address(sg);
293 sg_size_left = sg_dma_len(sg);
294 }
295
296 /* No room for an entire line, so chunk it up */
297 if (sg_size_left < line_len) {
298 int this_addr = fdma_addr;
299
300 while (line_len > 0) {
301 int this_write;
302
303 if (!sg_size_left) {
304 sg = sg_next(sg);
305 if (sg == NULL)
306 goto finish_buf;
307 sg_dma = sg_dma_address(sg);
308 sg_size_left = sg_dma_len(sg);
309 }
310
311 this_write = min(sg_size_left, line_len);
312
313 if (disp_push_desc(fh, sg_dma, this_addr,
314 this_write, 0, 0))
315 goto finish_buf;
316
317 line_len -= this_write;
318 sg_size_left -= this_write;
319 sg_dma += this_write;
320 this_addr += this_write;
321 }
322
323 fdma_addr += SOLO_HW_BPL;
324 continue;
325 }
326
327 /* Shove as many lines into a repeating descriptor as possible */
328 lines = min(sg_size_left / line_len,
329 solo_vlines(solo_dev) - i);
330
331 if (disp_push_desc(fh, sg_dma, fdma_addr, line_len,
332 lines - 1, SOLO_HW_BPL))
333 goto finish_buf;
334 229
335 i += lines - 1; 230 error = solo_p2m_dma_t(solo_dev, 0, vbuf, fdma_addr,
336 fdma_addr += SOLO_HW_BPL * lines; 231 solo_bytesperline(solo_dev),
337 sg_dma += lines * line_len; 232 solo_vlines(solo_dev), SOLO_HW_BPL);
338 sg_size_left -= lines * line_len;
339 } 233 }
340 234
341 error = disp_flush_descs(fh);
342
343finish_buf: 235finish_buf:
344 if (error) { 236 if (error) {
345 vb->state = VIDEOBUF_ERROR; 237 vb->state = VIDEOBUF_ERROR;
346 } else { 238 } else {
347 vb->size = solo_vlines(solo_dev) * solo_bytesperline(solo_dev);
348 vb->state = VIDEOBUF_DONE; 239 vb->state = VIDEOBUF_DONE;
349 vb->field_count++; 240 vb->field_count++;
350 do_gettimeofday(&vb->ts);
351 } 241 }
352 242
353 wake_up(&vb->done); 243 wake_up(&vb->done);
354
355 return;
356} 244}
357 245
358static void solo_thread_try(struct solo_filehandle *fh) 246static void solo_thread_try(struct solo_filehandle *fh)
359{ 247{
360 struct videobuf_buffer *vb; 248 struct videobuf_buffer *vb;
361 unsigned int cur_write;
362 249
250 /* Only "break" from this loop if slock is held, otherwise
251 * just return. */
363 for (;;) { 252 for (;;) {
253 unsigned int cur_write;
254
255 cur_write = SOLO_VI_STATUS0_PAGE(
256 solo_reg_read(fh->solo_dev, SOLO_VI_STATUS0));
257 if (cur_write == fh->old_write)
258 return;
259
364 spin_lock(&fh->slock); 260 spin_lock(&fh->slock);
365 261
366 if (list_empty(&fh->vidq_active)) 262 if (list_empty(&fh->vidq_active))
@@ -372,13 +268,9 @@ static void solo_thread_try(struct solo_filehandle *fh)
372 if (!waitqueue_active(&vb->done)) 268 if (!waitqueue_active(&vb->done))
373 break; 269 break;
374 270
375 cur_write = SOLO_VI_STATUS0_PAGE(solo_reg_read(fh->solo_dev,
376 SOLO_VI_STATUS0));
377 if (cur_write == fh->old_write)
378 break;
379
380 fh->old_write = cur_write; 271 fh->old_write = cur_write;
381 list_del(&vb->queue); 272 list_del(&vb->queue);
273 vb->state = VIDEOBUF_ACTIVE;
382 274
383 spin_unlock(&fh->slock); 275 spin_unlock(&fh->slock);
384 276
@@ -413,17 +305,31 @@ static int solo_thread(void *data)
413 305
414static int solo_start_thread(struct solo_filehandle *fh) 306static int solo_start_thread(struct solo_filehandle *fh)
415{ 307{
308 int ret = 0;
309
310 if (atomic_inc_return(&fh->solo_dev->disp_users) == 1)
311 solo_irq_on(fh->solo_dev, SOLO_IRQ_VIDEO_IN);
312
416 fh->kthread = kthread_run(solo_thread, fh, SOLO6X10_NAME "_disp"); 313 fh->kthread = kthread_run(solo_thread, fh, SOLO6X10_NAME "_disp");
417 314
418 return PTR_RET(fh->kthread); 315 if (IS_ERR(fh->kthread)) {
316 ret = PTR_ERR(fh->kthread);
317 fh->kthread = NULL;
318 }
319
320 return ret;
419} 321}
420 322
421static void solo_stop_thread(struct solo_filehandle *fh) 323static void solo_stop_thread(struct solo_filehandle *fh)
422{ 324{
423 if (fh->kthread) { 325 if (!fh->kthread)
424 kthread_stop(fh->kthread); 326 return;
425 fh->kthread = NULL; 327
426 } 328 kthread_stop(fh->kthread);
329 fh->kthread = NULL;
330
331 if (atomic_dec_return(&fh->solo_dev->disp_users) == 0)
332 solo_irq_off(fh->solo_dev, SOLO_IRQ_VIDEO_IN);
427} 333}
428 334
429static int solo_buf_setup(struct videobuf_queue *vq, unsigned int *count, 335static int solo_buf_setup(struct videobuf_queue *vq, unsigned int *count,
@@ -459,9 +365,7 @@ static int solo_buf_prepare(struct videobuf_queue *vq,
459 if (vb->state == VIDEOBUF_NEEDS_INIT) { 365 if (vb->state == VIDEOBUF_NEEDS_INIT) {
460 int rc = videobuf_iolock(vq, vb, NULL); 366 int rc = videobuf_iolock(vq, vb, NULL);
461 if (rc < 0) { 367 if (rc < 0) {
462 struct videobuf_dmabuf *dma = videobuf_to_dma(vb); 368 videobuf_dma_contig_free(vq, vb);
463 videobuf_dma_unmap(vq->dev, dma);
464 videobuf_dma_free(dma);
465 vb->state = VIDEOBUF_NEEDS_INIT; 369 vb->state = VIDEOBUF_NEEDS_INIT;
466 return rc; 370 return rc;
467 } 371 }
@@ -485,14 +389,11 @@ static void solo_buf_queue(struct videobuf_queue *vq,
485static void solo_buf_release(struct videobuf_queue *vq, 389static void solo_buf_release(struct videobuf_queue *vq,
486 struct videobuf_buffer *vb) 390 struct videobuf_buffer *vb)
487{ 391{
488 struct videobuf_dmabuf *dma = videobuf_to_dma(vb); 392 videobuf_dma_contig_free(vq, vb);
489
490 videobuf_dma_unmap(vq->dev, dma);
491 videobuf_dma_free(dma);
492 vb->state = VIDEOBUF_NEEDS_INIT; 393 vb->state = VIDEOBUF_NEEDS_INIT;
493} 394}
494 395
495static struct videobuf_queue_ops solo_video_qops = { 396static const struct videobuf_queue_ops solo_video_qops = {
496 .buf_setup = solo_buf_setup, 397 .buf_setup = solo_buf_setup,
497 .buf_prepare = solo_buf_prepare, 398 .buf_prepare = solo_buf_prepare,
498 .buf_queue = solo_buf_queue, 399 .buf_queue = solo_buf_queue,
@@ -535,12 +436,12 @@ static int solo_v4l2_open(struct file *file)
535 return ret; 436 return ret;
536 } 437 }
537 438
538 videobuf_queue_sg_init(&fh->vidq, &solo_video_qops, 439 videobuf_queue_dma_contig_init(&fh->vidq, &solo_video_qops,
539 &solo_dev->pdev->dev, &fh->slock, 440 &solo_dev->pdev->dev, &fh->slock,
540 V4L2_BUF_TYPE_VIDEO_CAPTURE, 441 V4L2_BUF_TYPE_VIDEO_CAPTURE,
541 SOLO_DISP_PIX_FIELD, 442 SOLO_DISP_PIX_FIELD,
542 sizeof(struct videobuf_buffer), fh, NULL); 443 sizeof(struct videobuf_buffer),
543 444 fh, NULL);
544 return 0; 445 return 0;
545} 446}
546 447
@@ -557,9 +458,11 @@ static int solo_v4l2_release(struct file *file)
557{ 458{
558 struct solo_filehandle *fh = file->private_data; 459 struct solo_filehandle *fh = file->private_data;
559 460
461 solo_stop_thread(fh);
462
560 videobuf_stop(&fh->vidq); 463 videobuf_stop(&fh->vidq);
561 videobuf_mmap_free(&fh->vidq); 464 videobuf_mmap_free(&fh->vidq);
562 solo_stop_thread(fh); 465
563 kfree(fh); 466 kfree(fh);
564 467
565 return 0; 468 return 0;
@@ -585,12 +488,12 @@ static int solo_querycap(struct file *file, void *priv,
585static int solo_enum_ext_input(struct solo_dev *solo_dev, 488static int solo_enum_ext_input(struct solo_dev *solo_dev,
586 struct v4l2_input *input) 489 struct v4l2_input *input)
587{ 490{
588 static const char *dispnames_1[] = { "4UP" }; 491 static const char * const dispnames_1[] = { "4UP" };
589 static const char *dispnames_2[] = { "4UP-1", "4UP-2" }; 492 static const char * const dispnames_2[] = { "4UP-1", "4UP-2" };
590 static const char *dispnames_5[] = { 493 static const char * const dispnames_5[] = {
591 "4UP-1", "4UP-2", "4UP-3", "4UP-4", "16UP" 494 "4UP-1", "4UP-2", "4UP-3", "4UP-4", "16UP"
592 }; 495 };
593 const char **dispnames; 496 const char * const *dispnames;
594 497
595 if (input->index >= (solo_dev->nr_chans + solo_dev->nr_ext)) 498 if (input->index >= (solo_dev->nr_chans + solo_dev->nr_ext))
596 return -EINVAL; 499 return -EINVAL;
@@ -640,8 +543,14 @@ static int solo_enum_input(struct file *file, void *priv,
640static int solo_set_input(struct file *file, void *priv, unsigned int index) 543static int solo_set_input(struct file *file, void *priv, unsigned int index)
641{ 544{
642 struct solo_filehandle *fh = priv; 545 struct solo_filehandle *fh = priv;
546 int ret = solo_v4l2_set_ch(fh->solo_dev, index);
547
548 if (!ret) {
549 while (erase_off(fh->solo_dev))
550 /* Do nothing */;
551 }
643 552
644 return solo_v4l2_set_ch(fh->solo_dev, index); 553 return ret;
645} 554}
646 555
647static int solo_get_input(struct file *file, void *priv, unsigned int *index) 556static int solo_get_input(struct file *file, void *priv, unsigned int *index)
@@ -732,7 +641,8 @@ static int solo_reqbufs(struct file *file, void *priv,
732 return videobuf_reqbufs(&fh->vidq, req); 641 return videobuf_reqbufs(&fh->vidq, req);
733} 642}
734 643
735static int solo_querybuf(struct file *file, void *priv, struct v4l2_buffer *buf) 644static int solo_querybuf(struct file *file, void *priv,
645 struct v4l2_buffer *buf)
736{ 646{
737 struct solo_filehandle *fh = priv; 647 struct solo_filehandle *fh = priv;
738 648
@@ -901,11 +811,12 @@ static struct video_device solo_v4l2_template = {
901 .current_norm = V4L2_STD_NTSC_M, 811 .current_norm = V4L2_STD_NTSC_M,
902}; 812};
903 813
904int solo_v4l2_init(struct solo_dev *solo_dev) 814int solo_v4l2_init(struct solo_dev *solo_dev, unsigned nr)
905{ 815{
906 int ret; 816 int ret;
907 int i; 817 int i;
908 818
819 atomic_set(&solo_dev->disp_users, 0);
909 init_waitqueue_head(&solo_dev->disp_thread_wait); 820 init_waitqueue_head(&solo_dev->disp_thread_wait);
910 821
911 solo_dev->vfd = video_device_alloc(); 822 solo_dev->vfd = video_device_alloc();
@@ -915,7 +826,7 @@ int solo_v4l2_init(struct solo_dev *solo_dev)
915 *solo_dev->vfd = solo_v4l2_template; 826 *solo_dev->vfd = solo_v4l2_template;
916 solo_dev->vfd->parent = &solo_dev->pdev->dev; 827 solo_dev->vfd->parent = &solo_dev->pdev->dev;
917 828
918 ret = video_register_device(solo_dev->vfd, VFL_TYPE_GRABBER, video_nr); 829 ret = video_register_device(solo_dev->vfd, VFL_TYPE_GRABBER, nr);
919 if (ret < 0) { 830 if (ret < 0) {
920 video_device_release(solo_dev->vfd); 831 video_device_release(solo_dev->vfd);
921 solo_dev->vfd = NULL; 832 solo_dev->vfd = NULL;
@@ -927,35 +838,30 @@ int solo_v4l2_init(struct solo_dev *solo_dev)
927 snprintf(solo_dev->vfd->name, sizeof(solo_dev->vfd->name), "%s (%i)", 838 snprintf(solo_dev->vfd->name, sizeof(solo_dev->vfd->name), "%s (%i)",
928 SOLO6X10_NAME, solo_dev->vfd->num); 839 SOLO6X10_NAME, solo_dev->vfd->num);
929 840
930 if (video_nr != -1) 841 dev_info(&solo_dev->pdev->dev,
931 video_nr++; 842 "Display as /dev/video%d with %d inputs (%d extended)\n",
932 843 solo_dev->vfd->num, solo_dev->nr_chans, solo_dev->nr_ext);
933 dev_info(&solo_dev->pdev->dev, "Display as /dev/video%d with "
934 "%d inputs (%d extended)\n", solo_dev->vfd->num,
935 solo_dev->nr_chans, solo_dev->nr_ext);
936 844
937 /* Cycle all the channels and clear */ 845 /* Cycle all the channels and clear */
938 for (i = 0; i < solo_dev->nr_chans; i++) { 846 for (i = 0; i < solo_dev->nr_chans; i++) {
939 solo_v4l2_set_ch(solo_dev, i); 847 solo_v4l2_set_ch(solo_dev, i);
940 while (erase_off(solo_dev)) 848 while (erase_off(solo_dev))
941 ;/* Do nothing */ 849 /* Do nothing */;
942 } 850 }
943 851
944 /* Set the default display channel */ 852 /* Set the default display channel */
945 solo_v4l2_set_ch(solo_dev, 0); 853 solo_v4l2_set_ch(solo_dev, 0);
946 while (erase_off(solo_dev)) 854 while (erase_off(solo_dev))
947 ;/* Do nothing */ 855 /* Do nothing */;
948
949 solo_irq_on(solo_dev, SOLO_IRQ_VIDEO_IN);
950 856
951 return 0; 857 return 0;
952} 858}
953 859
954void solo_v4l2_exit(struct solo_dev *solo_dev) 860void solo_v4l2_exit(struct solo_dev *solo_dev)
955{ 861{
956 solo_irq_off(solo_dev, SOLO_IRQ_VIDEO_IN); 862 if (solo_dev->vfd == NULL)
957 if (solo_dev->vfd) { 863 return;
958 video_unregister_device(solo_dev->vfd); 864
959 solo_dev->vfd = NULL; 865 video_unregister_device(solo_dev->vfd);
960 } 866 solo_dev->vfd = NULL;
961} 867}