1// SPDX-License-Identifier: GPL-2.0-or-later
2/*
3 * budget-core.c: driver for the SAA7146 based Budget DVB cards
4 *
5 * Compiled from various sources by Michael Hunold <michael@mihu.de>
6 *
7 * Copyright (C) 2002 Ralph Metzler <rjkm@metzlerbros.de>
8 *
9 * Copyright (C) 1999-2002 Ralph  Metzler
10 *			 & Marcus Metzler for convergence integrated media GmbH
11 *
12 * 26feb2004 Support for FS Activy Card (Grundig tuner) by
13 *	     Michael Dreher <michael@5dot1.de>,
14 *	     Oliver Endriss <o.endriss@gmx.de>,
15 *	     Andreas 'randy' Weinberger
16 *
17 * the project's page is at https://linuxtv.org
18 */
19
20
21#include "budget.h"
22#include "ttpci-eeprom.h"
23
24#define TS_WIDTH		(2 * TS_SIZE)
25#define TS_WIDTH_ACTIVY		TS_SIZE
26#define TS_WIDTH_DVBC		TS_SIZE
27#define TS_HEIGHT_MASK		0xf00
28#define TS_HEIGHT_MASK_ACTIVY	0xc00
29#define TS_HEIGHT_MASK_DVBC	0xe00
30#define TS_MIN_BUFSIZE_K	188
31#define TS_MAX_BUFSIZE_K	1410
32#define TS_MAX_BUFSIZE_K_ACTIVY	564
33#define TS_MAX_BUFSIZE_K_DVBC	1316
34#define BUFFER_WARNING_WAIT	(30*HZ)
35
36int budget_debug;
37static int dma_buffer_size = TS_MIN_BUFSIZE_K;
38module_param_named(debug, budget_debug, int, 0644);
39module_param_named(bufsize, dma_buffer_size, int, 0444);
40MODULE_PARM_DESC(debug, "Turn on/off budget debugging (default:off).");
41MODULE_PARM_DESC(bufsize, "DMA buffer size in KB, default: 188, min: 188, max: 1410 (Activy: 564)");
42
43/****************************************************************************
44 * TT budget / WinTV Nova
45 ****************************************************************************/
46
47static int stop_ts_capture(struct budget *budget)
48{
49	dprintk(2, "budget: %p\n", budget);
50
51	saa7146_write(budget->dev, MC1, MASK_20);	// DMA3 off
52	SAA7146_IER_DISABLE(budget->dev, MASK_10);
53	return 0;
54}
55
56static int start_ts_capture(struct budget *budget)
57{
58	struct saa7146_dev *dev = budget->dev;
59
60	dprintk(2, "budget: %p\n", budget);
61
62	if (!budget->feeding || !budget->fe_synced)
63		return 0;
64
65	saa7146_write(dev, MC1, MASK_20);	// DMA3 off
66
67	memset(budget->grabbing, 0x00, budget->buffer_size);
68
69	saa7146_write(dev, PCI_BT_V1, 0x001c0000 | (saa7146_read(dev, PCI_BT_V1) & ~0x001f0000));
70
71	budget->ttbp = 0;
72
73	/*
74	 *  Signal path on the Activy:
75	 *
76	 *  tuner -> SAA7146 port A -> SAA7146 BRS -> SAA7146 DMA3 -> memory
77	 *
78	 *  Since the tuner feeds 204 bytes packets into the SAA7146,
79	 *  DMA3 is configured to strip the trailing 16 FEC bytes:
80	 *      Pitch: 188, NumBytes3: 188, NumLines3: 1024
81	 */
82
83	switch(budget->card->type) {
84	case BUDGET_FS_ACTIVY:
85		saa7146_write(dev, DD1_INIT, 0x04000000);
86		saa7146_write(dev, MC2, (MASK_09 | MASK_25));
87		saa7146_write(dev, BRS_CTRL, 0x00000000);
88		break;
89	case BUDGET_PATCH:
90		saa7146_write(dev, DD1_INIT, 0x00000200);
91		saa7146_write(dev, MC2, (MASK_10 | MASK_26));
92		saa7146_write(dev, BRS_CTRL, 0x60000000);
93		break;
94	case BUDGET_CIN1200C_MK3:
95	case BUDGET_KNC1C_MK3:
96	case BUDGET_KNC1C_TDA10024:
97	case BUDGET_KNC1CP_MK3:
98		if (budget->video_port == BUDGET_VIDEO_PORTA) {
99			saa7146_write(dev, DD1_INIT, 0x06000200);
100			saa7146_write(dev, MC2, (MASK_09 | MASK_25 | MASK_10 | MASK_26));
101			saa7146_write(dev, BRS_CTRL, 0x00000000);
102		} else {
103			saa7146_write(dev, DD1_INIT, 0x00000600);
104			saa7146_write(dev, MC2, (MASK_09 | MASK_25 | MASK_10 | MASK_26));
105			saa7146_write(dev, BRS_CTRL, 0x60000000);
106		}
107		break;
108	default:
109		if (budget->video_port == BUDGET_VIDEO_PORTA) {
110			saa7146_write(dev, DD1_INIT, 0x06000200);
111			saa7146_write(dev, MC2, (MASK_09 | MASK_25 | MASK_10 | MASK_26));
112			saa7146_write(dev, BRS_CTRL, 0x00000000);
113		} else {
114			saa7146_write(dev, DD1_INIT, 0x02000600);
115			saa7146_write(dev, MC2, (MASK_09 | MASK_25 | MASK_10 | MASK_26));
116			saa7146_write(dev, BRS_CTRL, 0x60000000);
117		}
118	}
119
120	saa7146_write(dev, MC2, (MASK_08 | MASK_24));
121	mdelay(10);
122
123	saa7146_write(dev, BASE_ODD3, 0);
124	if (budget->buffer_size > budget->buffer_height * budget->buffer_width) {
125		// using odd/even buffers
126		saa7146_write(dev, BASE_EVEN3, budget->buffer_height * budget->buffer_width);
127	} else {
128		// using a single buffer
129		saa7146_write(dev, BASE_EVEN3, 0);
130	}
131	saa7146_write(dev, PROT_ADDR3, budget->buffer_size);
132	saa7146_write(dev, BASE_PAGE3, budget->pt.dma | ME1 | 0x90);
133
134	saa7146_write(dev, PITCH3, budget->buffer_width);
135	saa7146_write(dev, NUM_LINE_BYTE3,
136			(budget->buffer_height << 16) | budget->buffer_width);
137
138	saa7146_write(dev, MC2, (MASK_04 | MASK_20));
139
140	SAA7146_ISR_CLEAR(budget->dev, MASK_10);	/* VPE */
141	SAA7146_IER_ENABLE(budget->dev, MASK_10);	/* VPE */
142	saa7146_write(dev, MC1, (MASK_04 | MASK_20));	/* DMA3 on */
143
144	return 0;
145}
146
147static int budget_read_fe_status(struct dvb_frontend *fe,
148				 enum fe_status *status)
149{
150	struct budget *budget = fe->dvb->priv;
151	int synced;
152	int ret;
153
154	if (budget->read_fe_status)
155		ret = budget->read_fe_status(fe, status);
156	else
157		ret = -EINVAL;
158
159	if (!ret) {
160		synced = (*status & FE_HAS_LOCK);
161		if (synced != budget->fe_synced) {
162			budget->fe_synced = synced;
163			spin_lock(&budget->feedlock);
164			if (synced)
165				start_ts_capture(budget);
166			else
167				stop_ts_capture(budget);
168			spin_unlock(&budget->feedlock);
169		}
170	}
171	return ret;
172}
173
174static void vpeirq(struct tasklet_struct *t)
175{
176	struct budget *budget = from_tasklet(budget, t, vpe_tasklet);
177	u8 *mem = (u8 *) (budget->grabbing);
178	u32 olddma = budget->ttbp;
179	u32 newdma = saa7146_read(budget->dev, PCI_VDP3);
180	u32 count;
181
182	/* Ensure streamed PCI data is synced to CPU */
183	dma_sync_sg_for_cpu(&budget->dev->pci->dev, budget->pt.slist,
184			    budget->pt.nents, DMA_FROM_DEVICE);
185
186	/* nearest lower position divisible by 188 */
187	newdma -= newdma % 188;
188
189	if (newdma >= budget->buffer_size)
190		return;
191
192	budget->ttbp = newdma;
193
194	if (budget->feeding == 0 || newdma == olddma)
195		return;
196
197	if (newdma > olddma) {	/* no wraparound, dump olddma..newdma */
198		count = newdma - olddma;
199		dvb_dmx_swfilter_packets(&budget->demux, mem + olddma, count / 188);
200	} else {		/* wraparound, dump olddma..buflen and 0..newdma */
201		count = budget->buffer_size - olddma;
202		dvb_dmx_swfilter_packets(&budget->demux, mem + olddma, count / 188);
203		count += newdma;
204		dvb_dmx_swfilter_packets(&budget->demux, mem, newdma / 188);
205	}
206
207	if (count > budget->buffer_warning_threshold)
208		budget->buffer_warnings++;
209
210	if (budget->buffer_warnings && time_after(jiffies, budget->buffer_warning_time)) {
211		printk("%s %s: used %d times >80%% of buffer (%u bytes now)\n",
212			budget->dev->name, __func__, budget->buffer_warnings, count);
213		budget->buffer_warning_time = jiffies + BUFFER_WARNING_WAIT;
214		budget->buffer_warnings = 0;
215	}
216}
217
218
219static int ttpci_budget_debiread_nolock(struct budget *budget, u32 config,
220		int addr, int count, int nobusyloop)
221{
222	struct saa7146_dev *saa = budget->dev;
223	int result;
224
225	result = saa7146_wait_for_debi_done(saa, nobusyloop);
226	if (result < 0)
227		return result;
228
229	saa7146_write(saa, DEBI_COMMAND, (count << 17) | 0x10000 | (addr & 0xffff));
230	saa7146_write(saa, DEBI_CONFIG, config);
231	saa7146_write(saa, DEBI_PAGE, 0);
232	saa7146_write(saa, MC2, (2 << 16) | 2);
233
234	result = saa7146_wait_for_debi_done(saa, nobusyloop);
235	if (result < 0)
236		return result;
237
238	result = saa7146_read(saa, DEBI_AD);
239	result &= (0xffffffffUL >> ((4 - count) * 8));
240	return result;
241}
242
243int ttpci_budget_debiread(struct budget *budget, u32 config, int addr, int count,
244			  int uselocks, int nobusyloop)
245{
246	if (count > 4 || count <= 0)
247		return 0;
248
249	if (uselocks) {
250		unsigned long flags;
251		int result;
252
253		spin_lock_irqsave(&budget->debilock, flags);
254		result = ttpci_budget_debiread_nolock(budget, config, addr,
255						      count, nobusyloop);
256		spin_unlock_irqrestore(&budget->debilock, flags);
257		return result;
258	}
259	return ttpci_budget_debiread_nolock(budget, config, addr,
260					    count, nobusyloop);
261}
262
263static int ttpci_budget_debiwrite_nolock(struct budget *budget, u32 config,
264		int addr, int count, u32 value, int nobusyloop)
265{
266	struct saa7146_dev *saa = budget->dev;
267	int result;
268
269	result = saa7146_wait_for_debi_done(saa, nobusyloop);
270	if (result < 0)
271		return result;
272
273	saa7146_write(saa, DEBI_COMMAND, (count << 17) | 0x00000 | (addr & 0xffff));
274	saa7146_write(saa, DEBI_CONFIG, config);
275	saa7146_write(saa, DEBI_PAGE, 0);
276	saa7146_write(saa, DEBI_AD, value);
277	saa7146_write(saa, MC2, (2 << 16) | 2);
278
279	result = saa7146_wait_for_debi_done(saa, nobusyloop);
280	return result < 0 ? result : 0;
281}
282
283int ttpci_budget_debiwrite(struct budget *budget, u32 config, int addr,
284			   int count, u32 value, int uselocks, int nobusyloop)
285{
286	if (count > 4 || count <= 0)
287		return 0;
288
289	if (uselocks) {
290		unsigned long flags;
291		int result;
292
293		spin_lock_irqsave(&budget->debilock, flags);
294		result = ttpci_budget_debiwrite_nolock(budget, config, addr,
295						count, value, nobusyloop);
296		spin_unlock_irqrestore(&budget->debilock, flags);
297		return result;
298	}
299	return ttpci_budget_debiwrite_nolock(budget, config, addr,
300					     count, value, nobusyloop);
301}
302
303
304/****************************************************************************
305 * DVB API SECTION
306 ****************************************************************************/
307
308static int budget_start_feed(struct dvb_demux_feed *feed)
309{
310	struct dvb_demux *demux = feed->demux;
311	struct budget *budget = demux->priv;
312	int status = 0;
313
314	dprintk(2, "budget: %p\n", budget);
315
316	if (!demux->dmx.frontend)
317		return -EINVAL;
318
319	spin_lock(&budget->feedlock);
320	feed->pusi_seen = false; /* have a clean section start */
321	if (budget->feeding++ == 0)
322		status = start_ts_capture(budget);
323	spin_unlock(&budget->feedlock);
324	return status;
325}
326
327static int budget_stop_feed(struct dvb_demux_feed *feed)
328{
329	struct dvb_demux *demux = feed->demux;
330	struct budget *budget = demux->priv;
331	int status = 0;
332
333	dprintk(2, "budget: %p\n", budget);
334
335	spin_lock(&budget->feedlock);
336	if (--budget->feeding == 0)
337		status = stop_ts_capture(budget);
338	spin_unlock(&budget->feedlock);
339	return status;
340}
341
342static int budget_register(struct budget *budget)
343{
344	struct dvb_demux *dvbdemux = &budget->demux;
345	int ret;
346
347	dprintk(2, "budget: %p\n", budget);
348
349	dvbdemux->priv = (void *) budget;
350
351	dvbdemux->filternum = 256;
352	dvbdemux->feednum = 256;
353	dvbdemux->start_feed = budget_start_feed;
354	dvbdemux->stop_feed = budget_stop_feed;
355	dvbdemux->write_to_decoder = NULL;
356
357	dvbdemux->dmx.capabilities = (DMX_TS_FILTERING | DMX_SECTION_FILTERING |
358				      DMX_MEMORY_BASED_FILTERING);
359
360	dvb_dmx_init(&budget->demux);
361
362	budget->dmxdev.filternum = 256;
363	budget->dmxdev.demux = &dvbdemux->dmx;
364	budget->dmxdev.capabilities = 0;
365
366	dvb_dmxdev_init(&budget->dmxdev, &budget->dvb_adapter);
367
368	budget->hw_frontend.source = DMX_FRONTEND_0;
369
370	ret = dvbdemux->dmx.add_frontend(&dvbdemux->dmx, &budget->hw_frontend);
371
372	if (ret < 0)
373		goto err_release_dmx;
374
375	budget->mem_frontend.source = DMX_MEMORY_FE;
376	ret = dvbdemux->dmx.add_frontend(&dvbdemux->dmx, &budget->mem_frontend);
377	if (ret < 0)
378		goto err_release_dmx;
379
380	ret = dvbdemux->dmx.connect_frontend(&dvbdemux->dmx, &budget->hw_frontend);
381	if (ret < 0)
382		goto err_release_dmx;
383
384	dvb_net_init(&budget->dvb_adapter, &budget->dvb_net, &dvbdemux->dmx);
385
386	return 0;
387
388err_release_dmx:
389	dvb_dmxdev_release(&budget->dmxdev);
390	dvb_dmx_release(&budget->demux);
391	return ret;
392}
393
394static void budget_unregister(struct budget *budget)
395{
396	struct dvb_demux *dvbdemux = &budget->demux;
397
398	dprintk(2, "budget: %p\n", budget);
399
400	dvb_net_release(&budget->dvb_net);
401
402	dvbdemux->dmx.close(&dvbdemux->dmx);
403	dvbdemux->dmx.remove_frontend(&dvbdemux->dmx, &budget->hw_frontend);
404	dvbdemux->dmx.remove_frontend(&dvbdemux->dmx, &budget->mem_frontend);
405
406	dvb_dmxdev_release(&budget->dmxdev);
407	dvb_dmx_release(&budget->demux);
408}
409
410int ttpci_budget_init(struct budget *budget, struct saa7146_dev *dev,
411		      struct saa7146_pci_extension_data *info,
412		      struct module *owner, short *adapter_nums)
413{
414	int ret = 0;
415	struct budget_info *bi = info->ext_priv;
416	int max_bufsize;
417	int height_mask;
418
419	memset(budget, 0, sizeof(struct budget));
420
421	dprintk(2, "dev: %p, budget: %p\n", dev, budget);
422
423	budget->card = bi;
424	budget->dev = (struct saa7146_dev *) dev;
425
426	switch(budget->card->type) {
427	case BUDGET_FS_ACTIVY:
428		budget->buffer_width = TS_WIDTH_ACTIVY;
429		max_bufsize = TS_MAX_BUFSIZE_K_ACTIVY;
430		height_mask = TS_HEIGHT_MASK_ACTIVY;
431		break;
432
433	case BUDGET_KNC1C:
434	case BUDGET_KNC1CP:
435	case BUDGET_CIN1200C:
436	case BUDGET_KNC1C_MK3:
437	case BUDGET_KNC1C_TDA10024:
438	case BUDGET_KNC1CP_MK3:
439	case BUDGET_CIN1200C_MK3:
440		budget->buffer_width = TS_WIDTH_DVBC;
441		max_bufsize = TS_MAX_BUFSIZE_K_DVBC;
442		height_mask = TS_HEIGHT_MASK_DVBC;
443		break;
444
445	default:
446		budget->buffer_width = TS_WIDTH;
447		max_bufsize = TS_MAX_BUFSIZE_K;
448		height_mask = TS_HEIGHT_MASK;
449	}
450
451	if (dma_buffer_size < TS_MIN_BUFSIZE_K)
452		dma_buffer_size = TS_MIN_BUFSIZE_K;
453	else if (dma_buffer_size > max_bufsize)
454		dma_buffer_size = max_bufsize;
455
456	budget->buffer_height = dma_buffer_size * 1024 / budget->buffer_width;
457	if (budget->buffer_height > 0xfff) {
458		budget->buffer_height /= 2;
459		budget->buffer_height &= height_mask;
460		budget->buffer_size = 2 * budget->buffer_height * budget->buffer_width;
461	} else {
462		budget->buffer_height &= height_mask;
463		budget->buffer_size = budget->buffer_height * budget->buffer_width;
464	}
465	budget->buffer_warning_threshold = budget->buffer_size * 80/100;
466	budget->buffer_warnings = 0;
467	budget->buffer_warning_time = jiffies;
468
469	dprintk(2, "%s: buffer type = %s, width = %d, height = %d\n",
470		budget->dev->name,
471		budget->buffer_size > budget->buffer_width * budget->buffer_height ? "odd/even" : "single",
472		budget->buffer_width, budget->buffer_height);
473	printk("%s: dma buffer size %u\n", budget->dev->name, budget->buffer_size);
474
475	ret = dvb_register_adapter(&budget->dvb_adapter, budget->card->name,
476				   owner, &budget->dev->pci->dev, adapter_nums);
477	if (ret < 0)
478		return ret;
479
480	/* set dd1 stream a & b */
481	saa7146_write(dev, DD1_STREAM_B, 0x00000000);
482	saa7146_write(dev, MC2, (MASK_09 | MASK_25));
483	saa7146_write(dev, MC2, (MASK_10 | MASK_26));
484	saa7146_write(dev, DD1_INIT, 0x02000000);
485	saa7146_write(dev, MC2, (MASK_09 | MASK_25 | MASK_10 | MASK_26));
486
487	if (bi->type != BUDGET_FS_ACTIVY)
488		budget->video_port = BUDGET_VIDEO_PORTB;
489	else
490		budget->video_port = BUDGET_VIDEO_PORTA;
491	spin_lock_init(&budget->feedlock);
492	spin_lock_init(&budget->debilock);
493
494	/* the Siemens DVB needs this if you want to have the i2c chips
495	   get recognized before the main driver is loaded */
496	if (bi->type != BUDGET_FS_ACTIVY)
497		saa7146_write(dev, GPIO_CTRL, 0x500000);	/* GPIO 3 = 1 */
498
499	strscpy(budget->i2c_adap.name, budget->card->name,
500		sizeof(budget->i2c_adap.name));
501
502	saa7146_i2c_adapter_prepare(dev, &budget->i2c_adap, SAA7146_I2C_BUS_BIT_RATE_120);
503	strscpy(budget->i2c_adap.name, budget->card->name,
504		sizeof(budget->i2c_adap.name));
505
506	if (i2c_add_adapter(&budget->i2c_adap) < 0) {
507		ret = -ENOMEM;
508		goto err_dvb_unregister;
509	}
510
511	ttpci_eeprom_parse_mac(&budget->i2c_adap, budget->dvb_adapter.proposed_mac);
512
513	budget->grabbing = saa7146_vmalloc_build_pgtable(dev->pci, budget->buffer_size, &budget->pt);
514	if (NULL == budget->grabbing) {
515		ret = -ENOMEM;
516		goto err_del_i2c;
517	}
518
519	saa7146_write(dev, PCI_BT_V1, 0x001c0000);
520	/* upload all */
521	saa7146_write(dev, GPIO_CTRL, 0x000000);
522
523	tasklet_setup(&budget->vpe_tasklet, vpeirq);
524
525	/* frontend power on */
526	if (bi->type != BUDGET_FS_ACTIVY)
527		saa7146_setgpio(dev, 2, SAA7146_GPIO_OUTHI);
528
529	if ((ret = budget_register(budget)) == 0)
530		return 0; /* Everything OK */
531
532	/* An error occurred, cleanup resources */
533	saa7146_vfree_destroy_pgtable(dev->pci, budget->grabbing, &budget->pt);
534
535err_del_i2c:
536	i2c_del_adapter(&budget->i2c_adap);
537
538err_dvb_unregister:
539	dvb_unregister_adapter(&budget->dvb_adapter);
540
541	return ret;
542}
543
544void ttpci_budget_init_hooks(struct budget *budget)
545{
546	if (budget->dvb_frontend && !budget->read_fe_status) {
547		budget->read_fe_status = budget->dvb_frontend->ops.read_status;
548		budget->dvb_frontend->ops.read_status = budget_read_fe_status;
549	}
550}
551
552int ttpci_budget_deinit(struct budget *budget)
553{
554	struct saa7146_dev *dev = budget->dev;
555
556	dprintk(2, "budget: %p\n", budget);
557
558	budget_unregister(budget);
559
560	tasklet_kill(&budget->vpe_tasklet);
561
562	saa7146_vfree_destroy_pgtable(dev->pci, budget->grabbing, &budget->pt);
563
564	i2c_del_adapter(&budget->i2c_adap);
565
566	dvb_unregister_adapter(&budget->dvb_adapter);
567
568	return 0;
569}
570
571void ttpci_budget_irq10_handler(struct saa7146_dev *dev, u32 * isr)
572{
573	struct budget *budget = dev->ext_priv;
574
575	dprintk(8, "dev: %p, budget: %p\n", dev, budget);
576
577	if (*isr & MASK_10)
578		tasklet_schedule(&budget->vpe_tasklet);
579}
580
581void ttpci_budget_set_video_port(struct saa7146_dev *dev, int video_port)
582{
583	struct budget *budget = dev->ext_priv;
584
585	spin_lock(&budget->feedlock);
586	budget->video_port = video_port;
587	if (budget->feeding) {
588		stop_ts_capture(budget);
589		start_ts_capture(budget);
590	}
591	spin_unlock(&budget->feedlock);
592}
593
594EXPORT_SYMBOL_GPL(ttpci_budget_debiread);
595EXPORT_SYMBOL_GPL(ttpci_budget_debiwrite);
596EXPORT_SYMBOL_GPL(ttpci_budget_init);
597EXPORT_SYMBOL_GPL(ttpci_budget_init_hooks);
598EXPORT_SYMBOL_GPL(ttpci_budget_deinit);
599EXPORT_SYMBOL_GPL(ttpci_budget_irq10_handler);
600EXPORT_SYMBOL_GPL(ttpci_budget_set_video_port);
601EXPORT_SYMBOL_GPL(budget_debug);
602
603MODULE_LICENSE("GPL");
604