| Johannes Stezenbach | 2add87a | 2005-05-16 21:54:10 -0700 | [diff] [blame] | 1 | /* | 
| Uwe Bugla | 1589a99 | 2009-03-29 07:46:58 -0300 | [diff] [blame] | 2 |  * Linux driver for digital TV devices equipped with B2C2 FlexcopII(b)/III | 
 | 3 |  * flexcop-dma.c - configuring and controlling the DMA of the FlexCop | 
 | 4 |  * see flexcop.c for copyright information | 
| Johannes Stezenbach | 2add87a | 2005-05-16 21:54:10 -0700 | [diff] [blame] | 5 |  */ | 
 | 6 | #include "flexcop.h" | 
 | 7 |  | 
| Uwe Bugla | 1589a99 | 2009-03-29 07:46:58 -0300 | [diff] [blame] | 8 | int flexcop_dma_allocate(struct pci_dev *pdev, | 
 | 9 | 		struct flexcop_dma *dma, u32 size) | 
| Johannes Stezenbach | 2add87a | 2005-05-16 21:54:10 -0700 | [diff] [blame] | 10 | { | 
 | 11 | 	u8 *tcpu; | 
| Hans Verkuil | 614b147 | 2008-08-22 17:01:45 -0300 | [diff] [blame] | 12 | 	dma_addr_t tdma = 0; | 
| Johannes Stezenbach | 2add87a | 2005-05-16 21:54:10 -0700 | [diff] [blame] | 13 |  | 
 | 14 | 	if (size % 2) { | 
 | 15 | 		err("dma buffersize has to be even."); | 
 | 16 | 		return -EINVAL; | 
 | 17 | 	} | 
 | 18 |  | 
 | 19 | 	if ((tcpu = pci_alloc_consistent(pdev, size, &tdma)) != NULL) { | 
 | 20 | 		dma->pdev = pdev; | 
 | 21 | 		dma->cpu_addr0 = tcpu; | 
 | 22 | 		dma->dma_addr0 = tdma; | 
 | 23 | 		dma->cpu_addr1 = tcpu + size/2; | 
 | 24 | 		dma->dma_addr1 = tdma + size/2; | 
 | 25 | 		dma->size = size/2; | 
 | 26 | 		return 0; | 
 | 27 | 	} | 
 | 28 | 	return -ENOMEM; | 
 | 29 | } | 
 | 30 | EXPORT_SYMBOL(flexcop_dma_allocate); | 
 | 31 |  | 
 | 32 | void flexcop_dma_free(struct flexcop_dma *dma) | 
 | 33 | { | 
| Uwe Bugla | 1589a99 | 2009-03-29 07:46:58 -0300 | [diff] [blame] | 34 | 	pci_free_consistent(dma->pdev, dma->size*2, | 
 | 35 | 			dma->cpu_addr0, dma->dma_addr0); | 
| Johannes Stezenbach | 2add87a | 2005-05-16 21:54:10 -0700 | [diff] [blame] | 36 | 	memset(dma,0,sizeof(struct flexcop_dma)); | 
 | 37 | } | 
 | 38 | EXPORT_SYMBOL(flexcop_dma_free); | 
 | 39 |  | 
| Patrick Boettcher | 64221be | 2005-07-07 17:57:49 -0700 | [diff] [blame] | 40 | int flexcop_dma_config(struct flexcop_device *fc, | 
 | 41 | 		struct flexcop_dma *dma, | 
 | 42 | 		flexcop_dma_index_t dma_idx) | 
| Johannes Stezenbach | 2add87a | 2005-05-16 21:54:10 -0700 | [diff] [blame] | 43 | { | 
| Patrick Boettcher | 64221be | 2005-07-07 17:57:49 -0700 | [diff] [blame] | 44 | 	flexcop_ibi_value v0x0,v0x4,v0xc; | 
 | 45 | 	v0x0.raw = v0x4.raw = v0xc.raw = 0; | 
| Johannes Stezenbach | 2add87a | 2005-05-16 21:54:10 -0700 | [diff] [blame] | 46 |  | 
| Uwe Bugla | 1589a99 | 2009-03-29 07:46:58 -0300 | [diff] [blame] | 47 | 	v0x0.dma_0x0.dma_address0 = dma->dma_addr0 >> 2; | 
 | 48 | 	v0xc.dma_0xc.dma_address1 = dma->dma_addr1 >> 2; | 
| Patrick Boettcher | 64221be | 2005-07-07 17:57:49 -0700 | [diff] [blame] | 49 | 	v0x4.dma_0x4_write.dma_addr_size = dma->size / 4; | 
| Johannes Stezenbach | 2add87a | 2005-05-16 21:54:10 -0700 | [diff] [blame] | 50 |  | 
| Patrick Boettcher | 64221be | 2005-07-07 17:57:49 -0700 | [diff] [blame] | 51 | 	if ((dma_idx & FC_DMA_1) == dma_idx) { | 
 | 52 | 		fc->write_ibi_reg(fc,dma1_000,v0x0); | 
 | 53 | 		fc->write_ibi_reg(fc,dma1_004,v0x4); | 
 | 54 | 		fc->write_ibi_reg(fc,dma1_00c,v0xc); | 
 | 55 | 	} else if ((dma_idx & FC_DMA_2) == dma_idx) { | 
 | 56 | 		fc->write_ibi_reg(fc,dma2_010,v0x0); | 
 | 57 | 		fc->write_ibi_reg(fc,dma2_014,v0x4); | 
 | 58 | 		fc->write_ibi_reg(fc,dma2_01c,v0xc); | 
 | 59 | 	} else { | 
| Uwe Bugla | 1589a99 | 2009-03-29 07:46:58 -0300 | [diff] [blame] | 60 | 		err("either DMA1 or DMA2 can be configured within one " | 
 | 61 | 			"flexcop_dma_config call."); | 
| Patrick Boettcher | 64221be | 2005-07-07 17:57:49 -0700 | [diff] [blame] | 62 | 		return -EINVAL; | 
 | 63 | 	} | 
| Johannes Stezenbach | 2add87a | 2005-05-16 21:54:10 -0700 | [diff] [blame] | 64 |  | 
| Johannes Stezenbach | 2add87a | 2005-05-16 21:54:10 -0700 | [diff] [blame] | 65 | 	return 0; | 
 | 66 | } | 
| Patrick Boettcher | 64221be | 2005-07-07 17:57:49 -0700 | [diff] [blame] | 67 | EXPORT_SYMBOL(flexcop_dma_config); | 
| Johannes Stezenbach | 2add87a | 2005-05-16 21:54:10 -0700 | [diff] [blame] | 68 |  | 
| Patrick Boettcher | 64221be | 2005-07-07 17:57:49 -0700 | [diff] [blame] | 69 | /* start the DMA transfers, but not the DMA IRQs */ | 
 | 70 | int flexcop_dma_xfer_control(struct flexcop_device *fc, | 
 | 71 | 		flexcop_dma_index_t dma_idx, | 
 | 72 | 		flexcop_dma_addr_index_t index, | 
 | 73 | 		int onoff) | 
 | 74 | { | 
 | 75 | 	flexcop_ibi_value v0x0,v0xc; | 
 | 76 | 	flexcop_ibi_register r0x0,r0xc; | 
 | 77 |  | 
 | 78 | 	if ((dma_idx & FC_DMA_1) == dma_idx) { | 
 | 79 | 		r0x0 = dma1_000; | 
 | 80 | 		r0xc = dma1_00c; | 
 | 81 | 	} else if ((dma_idx & FC_DMA_2) == dma_idx) { | 
 | 82 | 		r0x0 = dma2_010; | 
 | 83 | 		r0xc = dma2_01c; | 
 | 84 | 	} else { | 
| Uwe Bugla | 1589a99 | 2009-03-29 07:46:58 -0300 | [diff] [blame] | 85 | 		err("either transfer DMA1 or DMA2 can be started within one " | 
 | 86 | 			"flexcop_dma_xfer_control call."); | 
| Patrick Boettcher | 64221be | 2005-07-07 17:57:49 -0700 | [diff] [blame] | 87 | 		return -EINVAL; | 
 | 88 | 	} | 
 | 89 |  | 
 | 90 | 	v0x0 = fc->read_ibi_reg(fc,r0x0); | 
 | 91 | 	v0xc = fc->read_ibi_reg(fc,r0xc); | 
 | 92 |  | 
 | 93 | 	deb_rdump("reg: %03x: %x\n",r0x0,v0x0.raw); | 
 | 94 | 	deb_rdump("reg: %03x: %x\n",r0xc,v0xc.raw); | 
 | 95 |  | 
 | 96 | 	if (index & FC_DMA_SUBADDR_0) | 
 | 97 | 		v0x0.dma_0x0.dma_0start = onoff; | 
 | 98 |  | 
 | 99 | 	if (index & FC_DMA_SUBADDR_1) | 
 | 100 | 		v0xc.dma_0xc.dma_1start = onoff; | 
 | 101 |  | 
 | 102 | 	fc->write_ibi_reg(fc,r0x0,v0x0); | 
 | 103 | 	fc->write_ibi_reg(fc,r0xc,v0xc); | 
 | 104 |  | 
 | 105 | 	deb_rdump("reg: %03x: %x\n",r0x0,v0x0.raw); | 
 | 106 | 	deb_rdump("reg: %03x: %x\n",r0xc,v0xc.raw); | 
 | 107 | 	return 0; | 
 | 108 | } | 
 | 109 | EXPORT_SYMBOL(flexcop_dma_xfer_control); | 
 | 110 |  | 
 | 111 | static int flexcop_dma_remap(struct flexcop_device *fc, | 
 | 112 | 		flexcop_dma_index_t dma_idx, | 
 | 113 | 		int onoff) | 
 | 114 | { | 
 | 115 | 	flexcop_ibi_register r = (dma_idx & FC_DMA_1) ? dma1_00c : dma2_01c; | 
 | 116 | 	flexcop_ibi_value v = fc->read_ibi_reg(fc,r); | 
| Harvey Harrison | 7bca449 | 2008-04-08 23:20:00 -0300 | [diff] [blame] | 117 | 	deb_info("%s\n",__func__); | 
| Patrick Boettcher | 64221be | 2005-07-07 17:57:49 -0700 | [diff] [blame] | 118 | 	v.dma_0xc.remap_enable = onoff; | 
 | 119 | 	fc->write_ibi_reg(fc,r,v); | 
 | 120 | 	return 0; | 
 | 121 | } | 
 | 122 |  | 
 | 123 | int flexcop_dma_control_size_irq(struct flexcop_device *fc, | 
 | 124 | 		flexcop_dma_index_t no, | 
 | 125 | 		int onoff) | 
| Johannes Stezenbach | 2add87a | 2005-05-16 21:54:10 -0700 | [diff] [blame] | 126 | { | 
 | 127 | 	flexcop_ibi_value v = fc->read_ibi_reg(fc,ctrl_208); | 
 | 128 |  | 
 | 129 | 	if (no & FC_DMA_1) | 
 | 130 | 		v.ctrl_208.DMA1_IRQ_Enable_sig = onoff; | 
 | 131 |  | 
 | 132 | 	if (no & FC_DMA_2) | 
 | 133 | 		v.ctrl_208.DMA2_IRQ_Enable_sig = onoff; | 
 | 134 |  | 
 | 135 | 	fc->write_ibi_reg(fc,ctrl_208,v); | 
 | 136 | 	return 0; | 
 | 137 | } | 
 | 138 | EXPORT_SYMBOL(flexcop_dma_control_size_irq); | 
 | 139 |  | 
| Patrick Boettcher | 64221be | 2005-07-07 17:57:49 -0700 | [diff] [blame] | 140 | int flexcop_dma_control_timer_irq(struct flexcop_device *fc, | 
 | 141 | 		flexcop_dma_index_t no, | 
 | 142 | 		int onoff) | 
| Johannes Stezenbach | 2add87a | 2005-05-16 21:54:10 -0700 | [diff] [blame] | 143 | { | 
 | 144 | 	flexcop_ibi_value v = fc->read_ibi_reg(fc,ctrl_208); | 
 | 145 |  | 
 | 146 | 	if (no & FC_DMA_1) | 
| Patrick Boettcher | 64221be | 2005-07-07 17:57:49 -0700 | [diff] [blame] | 147 | 		v.ctrl_208.DMA1_Timer_Enable_sig = onoff; | 
 | 148 |  | 
 | 149 | 	if (no & FC_DMA_2) | 
 | 150 | 		v.ctrl_208.DMA2_Timer_Enable_sig = onoff; | 
 | 151 |  | 
 | 152 | 	fc->write_ibi_reg(fc,ctrl_208,v); | 
 | 153 | 	return 0; | 
 | 154 | } | 
 | 155 | EXPORT_SYMBOL(flexcop_dma_control_timer_irq); | 
 | 156 |  | 
 | 157 | /* 1 cycles = 1.97 msec */ | 
 | 158 | int flexcop_dma_config_timer(struct flexcop_device *fc, | 
| Uwe Bugla | 1589a99 | 2009-03-29 07:46:58 -0300 | [diff] [blame] | 159 | 		flexcop_dma_index_t dma_idx, u8 cycles) | 
| Patrick Boettcher | 64221be | 2005-07-07 17:57:49 -0700 | [diff] [blame] | 160 | { | 
 | 161 | 	flexcop_ibi_register r = (dma_idx & FC_DMA_1) ? dma1_004 : dma2_014; | 
 | 162 | 	flexcop_ibi_value v = fc->read_ibi_reg(fc,r); | 
 | 163 |  | 
 | 164 | 	flexcop_dma_remap(fc,dma_idx,0); | 
 | 165 |  | 
| Harvey Harrison | 7bca449 | 2008-04-08 23:20:00 -0300 | [diff] [blame] | 166 | 	deb_info("%s\n",__func__); | 
| Patrick Boettcher | 64221be | 2005-07-07 17:57:49 -0700 | [diff] [blame] | 167 | 	v.dma_0x4_write.dmatimer = cycles; | 
 | 168 | 	fc->write_ibi_reg(fc,r,v); | 
 | 169 | 	return 0; | 
 | 170 | } | 
 | 171 | EXPORT_SYMBOL(flexcop_dma_config_timer); | 
 | 172 |  |