1866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman/*
2866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman * Copyright (C) 2005-2006 Micronas USA Inc.
3866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman *
4866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman * This program is free software; you can redistribute it and/or modify
5866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman * it under the terms of the GNU General Public License (Version 2) as
6866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman * published by the Free Software Foundation.
7866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman *
8866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman * This program is distributed in the hope that it will be useful,
9866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman * but WITHOUT ANY WARRANTY; without even the implied warranty of
10866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman * GNU General Public License for more details.
12866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman *
13866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman * You should have received a copy of the GNU General Public License
14866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman * along with this program; if not, write to the Free Software Foundation,
15866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman * Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
16866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman */
17866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman
18866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman#include <linux/module.h>
19866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman#include <linux/kernel.h>
20866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman#include <linux/init.h>
21866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman#include <linux/spinlock.h>
22866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman#include <linux/wait.h>
23866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman#include <linux/list.h>
24866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman#include <linux/slab.h>
25866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman#include <linux/time.h>
26866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman#include <linux/mm.h>
27866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman#include <linux/usb.h>
28866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman#include <linux/i2c.h>
29866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman#include <asm/byteorder.h>
30d73f822ce775e004836ffc01ce9feae27d0d65cfPete Eberlein#include <media/v4l2-common.h>
31866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman
32866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman#include "saa7134-reg.h"
33866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman#include "saa7134.h"
34866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman#include "go7007-priv.h"
35866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman
36866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman#define GO7007_HPI_DEBUG
37866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman
38866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartmanenum hpi_address {
39866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman	HPI_ADDR_VIDEO_BUFFER = 0xe4,
40866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman	HPI_ADDR_INIT_BUFFER = 0xea,
41866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman	HPI_ADDR_INTR_RET_VALUE = 0xee,
42866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman	HPI_ADDR_INTR_RET_DATA = 0xec,
43866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman	HPI_ADDR_INTR_STATUS = 0xf4,
44866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman	HPI_ADDR_INTR_WR_PARAM = 0xf6,
45866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman	HPI_ADDR_INTR_WR_INDEX = 0xf8,
46866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman};
47866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman
48866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartmanenum gpio_command {
49866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman	GPIO_COMMAND_RESET = 0x00, /* 000b */
50866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman	GPIO_COMMAND_REQ1  = 0x04, /* 001b */
51866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman	GPIO_COMMAND_WRITE = 0x20, /* 010b */
52866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman	GPIO_COMMAND_REQ2  = 0x24, /* 011b */
53866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman	GPIO_COMMAND_READ  = 0x80, /* 100b */
54866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman	GPIO_COMMAND_VIDEO = 0x84, /* 101b */
55866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman	GPIO_COMMAND_IDLE  = 0xA0, /* 110b */
56866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman	GPIO_COMMAND_ADDR  = 0xA4, /* 111b */
57866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman};
58866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman
59866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartmanstruct saa7134_go7007 {
60866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman	struct saa7134_dev *dev;
61866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman	u8 *top;
62866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman	u8 *bottom;
63866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman	dma_addr_t top_dma;
64866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman	dma_addr_t bottom_dma;
65866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman};
66866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman
67866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartmanstatic struct go7007_board_info board_voyager = {
68866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman	.firmware	 = "go7007tv.bin",
69866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman	.flags		 = 0,
70866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman	.sensor_flags	 = GO7007_SENSOR_656 |
71866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman				GO7007_SENSOR_VALID_ENABLE |
72866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman				GO7007_SENSOR_TV |
73866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman				GO7007_SENSOR_VBI,
74866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman	.audio_flags	= GO7007_AUDIO_I2S_MODE_1 |
75866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman				GO7007_AUDIO_WORD_16,
76866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman	.audio_rate	 = 48000,
77866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman	.audio_bclk_div	 = 8,
78866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman	.audio_main_div	 = 2,
79866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman	.hpi_buffer_cap  = 7,
80866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman	.num_inputs	 = 1,
81866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman	.inputs 	 = {
82866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman		{
83866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman			.name		= "SAA7134",
84866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman		},
85866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman	},
86866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman};
875d929a71908968905331cda0d52c44570d402110Ben HutchingsMODULE_FIRMWARE("go7007tv.bin");
88866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman
89866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman/********************* Driver for GPIO HPI interface *********************/
90866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman
91866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartmanstatic int gpio_write(struct saa7134_dev *dev, u8 addr, u16 data)
92866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman{
93866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman	saa_writeb(SAA7134_GPIO_GPMODE0, 0xff);
94866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman
95866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman	/* Write HPI address */
96866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman	saa_writeb(SAA7134_GPIO_GPSTATUS0, addr);
97866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman	saa_writeb(SAA7134_GPIO_GPSTATUS2, GPIO_COMMAND_ADDR);
98866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman	saa_writeb(SAA7134_GPIO_GPSTATUS2, GPIO_COMMAND_IDLE);
99866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman
100866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman	/* Write low byte */
101866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman	saa_writeb(SAA7134_GPIO_GPSTATUS0, data & 0xff);
102866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman	saa_writeb(SAA7134_GPIO_GPSTATUS2, GPIO_COMMAND_WRITE);
103866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman	saa_writeb(SAA7134_GPIO_GPSTATUS2, GPIO_COMMAND_IDLE);
104866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman
105866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman	/* Write high byte */
106866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman	saa_writeb(SAA7134_GPIO_GPSTATUS0, data >> 8);
107866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman	saa_writeb(SAA7134_GPIO_GPSTATUS2, GPIO_COMMAND_WRITE);
108866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman	saa_writeb(SAA7134_GPIO_GPSTATUS2, GPIO_COMMAND_IDLE);
109866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman
110866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman	return 0;
111866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman}
112866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman
113866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartmanstatic int gpio_read(struct saa7134_dev *dev, u8 addr, u16 *data)
114866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman{
115866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman	saa_writeb(SAA7134_GPIO_GPMODE0, 0xff);
116866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman
117866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman	/* Write HPI address */
118866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman	saa_writeb(SAA7134_GPIO_GPSTATUS0, addr);
119866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman	saa_writeb(SAA7134_GPIO_GPSTATUS2, GPIO_COMMAND_ADDR);
120866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman	saa_writeb(SAA7134_GPIO_GPSTATUS2, GPIO_COMMAND_IDLE);
121866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman
122866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman	saa_writeb(SAA7134_GPIO_GPMODE0, 0x00);
123866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman
124866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman	/* Read low byte */
125866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman	saa_writeb(SAA7134_GPIO_GPSTATUS2, GPIO_COMMAND_READ);
126866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman	saa_clearb(SAA7134_GPIO_GPMODE3, SAA7134_GPIO_GPRESCAN);
127866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman	saa_setb(SAA7134_GPIO_GPMODE3, SAA7134_GPIO_GPRESCAN);
128866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman	*data = saa_readb(SAA7134_GPIO_GPSTATUS0);
129866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman	saa_writeb(SAA7134_GPIO_GPSTATUS2, GPIO_COMMAND_IDLE);
130866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman
131866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman	/* Read high byte */
132866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman	saa_writeb(SAA7134_GPIO_GPSTATUS2, GPIO_COMMAND_READ);
133866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman	saa_clearb(SAA7134_GPIO_GPMODE3, SAA7134_GPIO_GPRESCAN);
134866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman	saa_setb(SAA7134_GPIO_GPMODE3, SAA7134_GPIO_GPRESCAN);
135866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman	*data |= saa_readb(SAA7134_GPIO_GPSTATUS0) << 8;
136866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman	saa_writeb(SAA7134_GPIO_GPSTATUS2, GPIO_COMMAND_IDLE);
137866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman
138866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman	return 0;
139866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman}
140866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman
141866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartmanstatic int saa7134_go7007_interface_reset(struct go7007 *go)
142866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman{
143866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman	struct saa7134_go7007 *saa = go->hpi_context;
144866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman	struct saa7134_dev *dev = saa->dev;
145866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman	u32 status;
146866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman	u16 intr_val, intr_data;
147866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman	int count = 20;
148866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman
149866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman	saa_clearb(SAA7134_TS_PARALLEL, 0x80); /* Disable TS interface */
150866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman	saa_writeb(SAA7134_GPIO_GPMODE2, 0xa4);
151866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman	saa_writeb(SAA7134_GPIO_GPMODE0, 0xff);
152866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman
153866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman	saa_writeb(SAA7134_GPIO_GPSTATUS2, GPIO_COMMAND_REQ1);
154866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman	saa_writeb(SAA7134_GPIO_GPSTATUS2, GPIO_COMMAND_RESET);
155866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman	msleep(1);
156866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman	saa_writeb(SAA7134_GPIO_GPSTATUS2, GPIO_COMMAND_REQ1);
157866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman	saa_writeb(SAA7134_GPIO_GPSTATUS2, GPIO_COMMAND_REQ2);
158866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman	msleep(10);
159866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman
160866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman	saa_clearb(SAA7134_GPIO_GPMODE3, SAA7134_GPIO_GPRESCAN);
161866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman	saa_setb(SAA7134_GPIO_GPMODE3, SAA7134_GPIO_GPRESCAN);
162866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman
163866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman	status = saa_readb(SAA7134_GPIO_GPSTATUS2);
164866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman	/*printk(KERN_DEBUG "status is %s\n", status & 0x40 ? "OK" : "not OK"); */
165866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman
166866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman	/* enter command mode...(?) */
167866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman	saa_writeb(SAA7134_GPIO_GPSTATUS2, GPIO_COMMAND_REQ1);
168866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman	saa_writeb(SAA7134_GPIO_GPSTATUS2, GPIO_COMMAND_REQ2);
169866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman
170866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman	do {
171866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman		saa_clearb(SAA7134_GPIO_GPMODE3, SAA7134_GPIO_GPRESCAN);
172866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman		saa_setb(SAA7134_GPIO_GPMODE3, SAA7134_GPIO_GPRESCAN);
173866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman		status = saa_readb(SAA7134_GPIO_GPSTATUS2);
174866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman		/*printk(KERN_INFO "gpio is %08x\n", saa_readl(SAA7134_GPIO_GPSTATUS0 >> 2)); */
175866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman	} while (--count > 0);
176866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman
177866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman	/* Wait for an interrupt to indicate successful hardware reset */
178866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman	if (go7007_read_interrupt(go, &intr_val, &intr_data) < 0 ||
179866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman			(intr_val & ~0x1) != 0x55aa) {
180866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman		printk(KERN_ERR
181866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman			"saa7134-go7007: unable to reset the GO7007\n");
182866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman		return -1;
183866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman	}
184866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman	return 0;
185866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman}
186866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman
187866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartmanstatic int saa7134_go7007_write_interrupt(struct go7007 *go, int addr, int data)
188866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman{
189866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman	struct saa7134_go7007 *saa = go->hpi_context;
190866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman	struct saa7134_dev *dev = saa->dev;
191866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman	int i;
192866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman	u16 status_reg;
193866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman
194866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman#ifdef GO7007_HPI_DEBUG
195866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman	printk(KERN_DEBUG
196866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman		"saa7134-go7007: WriteInterrupt: %04x %04x\n", addr, data);
197866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman#endif
198866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman
199866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman	for (i = 0; i < 100; ++i) {
200866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman		gpio_read(dev, HPI_ADDR_INTR_STATUS, &status_reg);
201866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman		if (!(status_reg & 0x0010))
202866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman			break;
203866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman		msleep(10);
204866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman	}
205866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman	if (i == 100) {
206866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman		printk(KERN_ERR
207866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman			"saa7134-go7007: device is hung, status reg = 0x%04x\n",
208866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman			status_reg);
209866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman		return -1;
210866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman	}
211866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman	gpio_write(dev, HPI_ADDR_INTR_WR_PARAM, data);
212866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman	gpio_write(dev, HPI_ADDR_INTR_WR_INDEX, addr);
213866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman
214866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman	return 0;
215866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman}
216866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman
217866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartmanstatic int saa7134_go7007_read_interrupt(struct go7007 *go)
218866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman{
219866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman	struct saa7134_go7007 *saa = go->hpi_context;
220866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman	struct saa7134_dev *dev = saa->dev;
221866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman
222866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman	/* XXX we need to wait if there is no interrupt available */
223866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman	go->interrupt_available = 1;
224866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman	gpio_read(dev, HPI_ADDR_INTR_RET_VALUE, &go->interrupt_value);
225866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman	gpio_read(dev, HPI_ADDR_INTR_RET_DATA, &go->interrupt_data);
226866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman#ifdef GO7007_HPI_DEBUG
227866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman	printk(KERN_DEBUG "saa7134-go7007: ReadInterrupt: %04x %04x\n",
228866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman			go->interrupt_value, go->interrupt_data);
229866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman#endif
230866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman	return 0;
231866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman}
232866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman
233866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartmanstatic void saa7134_go7007_irq_ts_done(struct saa7134_dev *dev,
234866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman						unsigned long status)
235866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman{
236866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman	struct go7007 *go = video_get_drvdata(dev->empress_dev);
237866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman	struct saa7134_go7007 *saa = go->hpi_context;
238866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman
239866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman	if (!go->streaming)
240866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman		return;
241866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman	if (0 != (status & 0x000f0000))
242866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman		printk(KERN_DEBUG "saa7134-go7007: irq: lost %ld\n",
243866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman				(status >> 16) & 0x0f);
244866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman	if (status & 0x100000) {
2456d256fa8868b4509310ea201c2d2c04fabea96abFUJITA Tomonori		dma_sync_single_for_cpu(&dev->pci->dev,
2466d256fa8868b4509310ea201c2d2c04fabea96abFUJITA Tomonori					saa->bottom_dma, PAGE_SIZE, DMA_FROM_DEVICE);
247866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman		go7007_parse_video_stream(go, saa->bottom, PAGE_SIZE);
248866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman		saa_writel(SAA7134_RS_BA2(5), cpu_to_le32(saa->bottom_dma));
249866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman	} else {
2506d256fa8868b4509310ea201c2d2c04fabea96abFUJITA Tomonori		dma_sync_single_for_cpu(&dev->pci->dev,
2516d256fa8868b4509310ea201c2d2c04fabea96abFUJITA Tomonori					saa->top_dma, PAGE_SIZE, DMA_FROM_DEVICE);
252866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman		go7007_parse_video_stream(go, saa->top, PAGE_SIZE);
253866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman		saa_writel(SAA7134_RS_BA1(5), cpu_to_le32(saa->top_dma));
254866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman	}
255866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman}
256866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman
257866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartmanstatic int saa7134_go7007_stream_start(struct go7007 *go)
258866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman{
259866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman	struct saa7134_go7007 *saa = go->hpi_context;
260866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman	struct saa7134_dev *dev = saa->dev;
261866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman
262866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman	saa->top_dma = dma_map_page(&dev->pci->dev, virt_to_page(saa->top),
263866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman			0, PAGE_SIZE, DMA_FROM_DEVICE);
264866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman	if (!saa->top_dma)
265866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman		return -ENOMEM;
266866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman	saa->bottom_dma = dma_map_page(&dev->pci->dev,
267866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman			virt_to_page(saa->bottom),
268866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman			0, PAGE_SIZE, DMA_FROM_DEVICE);
269866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman	if (!saa->bottom_dma) {
270866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman		dma_unmap_page(&dev->pci->dev, saa->top_dma, PAGE_SIZE,
271866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman				DMA_FROM_DEVICE);
272866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman		return -ENOMEM;
273866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman	}
274866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman
275866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman	saa_writel(SAA7134_VIDEO_PORT_CTRL0 >> 2, 0xA300B000);
276866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman	saa_writel(SAA7134_VIDEO_PORT_CTRL4 >> 2, 0x40000200);
277866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman
278866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman	/* Set HPI interface for video */
279866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman	saa_writeb(SAA7134_GPIO_GPMODE0, 0xff);
280866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman	saa_writeb(SAA7134_GPIO_GPSTATUS0, HPI_ADDR_VIDEO_BUFFER);
281866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman	saa_writeb(SAA7134_GPIO_GPSTATUS2, GPIO_COMMAND_ADDR);
282866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman	saa_writeb(SAA7134_GPIO_GPMODE0, 0x00);
283866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman
284866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman	/* Enable TS interface */
285866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman	saa_writeb(SAA7134_TS_PARALLEL, 0xe6);
286866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman
287866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman	/* Reset TS interface */
288866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman	saa_setb(SAA7134_TS_SERIAL1, 0x01);
289866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman	saa_clearb(SAA7134_TS_SERIAL1, 0x01);
290866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman
291866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman	/* Set up transfer block size */
292866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman	saa_writeb(SAA7134_TS_PARALLEL_SERIAL, 128 - 1);
293866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman	saa_writeb(SAA7134_TS_DMA0, (PAGE_SIZE >> 7) - 1);
294866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman	saa_writeb(SAA7134_TS_DMA1, 0);
295866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman	saa_writeb(SAA7134_TS_DMA2, 0);
296866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman
297866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman	/* Enable video streaming mode */
298866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman	saa_writeb(SAA7134_GPIO_GPSTATUS2, GPIO_COMMAND_VIDEO);
299866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman
300866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman	saa_writel(SAA7134_RS_BA1(5), cpu_to_le32(saa->top_dma));
301866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman	saa_writel(SAA7134_RS_BA2(5), cpu_to_le32(saa->bottom_dma));
302866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman	saa_writel(SAA7134_RS_PITCH(5), 128);
303866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman	saa_writel(SAA7134_RS_CONTROL(5), SAA7134_RS_CONTROL_BURST_MAX);
304866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman
305866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman	/* Enable TS FIFO */
306866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman	saa_setl(SAA7134_MAIN_CTRL, SAA7134_MAIN_CTRL_TE5);
307866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman
308866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman	/* Enable DMA IRQ */
309866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman	saa_setl(SAA7134_IRQ1,
310866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman			SAA7134_IRQ1_INTE_RA2_1 | SAA7134_IRQ1_INTE_RA2_0);
311866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman
312866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman	return 0;
313866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman}
314866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman
315866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartmanstatic int saa7134_go7007_stream_stop(struct go7007 *go)
316866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman{
317866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman	struct saa7134_go7007 *saa = go->hpi_context;
318d73f822ce775e004836ffc01ce9feae27d0d65cfPete Eberlein	struct saa7134_dev *dev;
319d73f822ce775e004836ffc01ce9feae27d0d65cfPete Eberlein
320d73f822ce775e004836ffc01ce9feae27d0d65cfPete Eberlein	if (!saa)
321d73f822ce775e004836ffc01ce9feae27d0d65cfPete Eberlein		return -EINVAL;
322d73f822ce775e004836ffc01ce9feae27d0d65cfPete Eberlein	dev = saa->dev;
323d73f822ce775e004836ffc01ce9feae27d0d65cfPete Eberlein	if (!dev)
324d73f822ce775e004836ffc01ce9feae27d0d65cfPete Eberlein		return -EINVAL;
325866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman
326866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman	/* Shut down TS FIFO */
327866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman	saa_clearl(SAA7134_MAIN_CTRL, SAA7134_MAIN_CTRL_TE5);
328866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman
329866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman	/* Disable DMA IRQ */
330866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman	saa_clearl(SAA7134_IRQ1,
331866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman			SAA7134_IRQ1_INTE_RA2_1 | SAA7134_IRQ1_INTE_RA2_0);
332866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman
333866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman	/* Disable TS interface */
334866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman	saa_clearb(SAA7134_TS_PARALLEL, 0x80);
335866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman
336866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman	dma_unmap_page(&dev->pci->dev, saa->top_dma, PAGE_SIZE,
337866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman			DMA_FROM_DEVICE);
338866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman	dma_unmap_page(&dev->pci->dev, saa->bottom_dma, PAGE_SIZE,
339866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman			DMA_FROM_DEVICE);
340866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman
341866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman	return 0;
342866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman}
343866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman
344866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartmanstatic int saa7134_go7007_send_firmware(struct go7007 *go, u8 *data, int len)
345866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman{
346866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman	struct saa7134_go7007 *saa = go->hpi_context;
347866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman	struct saa7134_dev *dev = saa->dev;
348866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman	u16 status_reg;
349866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman	int i;
350866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman
351866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman#ifdef GO7007_HPI_DEBUG
352866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman	printk(KERN_DEBUG "saa7134-go7007: DownloadBuffer "
353866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman			"sending %d bytes\n", len);
354866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman#endif
355866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman
356866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman	while (len > 0) {
357866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman		i = len > 64 ? 64 : len;
358866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman		saa_writeb(SAA7134_GPIO_GPMODE0, 0xff);
359866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman		saa_writeb(SAA7134_GPIO_GPSTATUS0, HPI_ADDR_INIT_BUFFER);
360866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman		saa_writeb(SAA7134_GPIO_GPSTATUS2, GPIO_COMMAND_ADDR);
361866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman		saa_writeb(SAA7134_GPIO_GPSTATUS2, GPIO_COMMAND_IDLE);
362866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman		while (i-- > 0) {
363866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman			saa_writeb(SAA7134_GPIO_GPSTATUS0, *data);
364866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman			saa_writeb(SAA7134_GPIO_GPSTATUS2, GPIO_COMMAND_WRITE);
365866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman			saa_writeb(SAA7134_GPIO_GPSTATUS2, GPIO_COMMAND_IDLE);
366866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman			++data;
367866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman			--len;
368866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman		}
369866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman		for (i = 0; i < 100; ++i) {
370866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman			gpio_read(dev, HPI_ADDR_INTR_STATUS, &status_reg);
371866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman			if (!(status_reg & 0x0002))
372866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman				break;
373866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman		}
374866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman		if (i == 100) {
375866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman			printk(KERN_ERR "saa7134-go7007: device is hung, "
376866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman					"status reg = 0x%04x\n", status_reg);
377866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman			return -1;
378866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman		}
379866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman	}
380866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman	return 0;
381866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman}
382866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman
383d73f822ce775e004836ffc01ce9feae27d0d65cfPete Eberleinstatic int saa7134_go7007_send_command(struct go7007 *go, unsigned int cmd,
384d73f822ce775e004836ffc01ce9feae27d0d65cfPete Eberlein					void *arg)
385d73f822ce775e004836ffc01ce9feae27d0d65cfPete Eberlein{
386d73f822ce775e004836ffc01ce9feae27d0d65cfPete Eberlein	struct saa7134_go7007 *saa = go->hpi_context;
387d73f822ce775e004836ffc01ce9feae27d0d65cfPete Eberlein	struct saa7134_dev *dev = saa->dev;
388d73f822ce775e004836ffc01ce9feae27d0d65cfPete Eberlein
389d73f822ce775e004836ffc01ce9feae27d0d65cfPete Eberlein	switch (cmd) {
390d73f822ce775e004836ffc01ce9feae27d0d65cfPete Eberlein	case VIDIOC_S_STD:
391d73f822ce775e004836ffc01ce9feae27d0d65cfPete Eberlein	{
392d73f822ce775e004836ffc01ce9feae27d0d65cfPete Eberlein		v4l2_std_id *std = arg;
393d73f822ce775e004836ffc01ce9feae27d0d65cfPete Eberlein		return saa7134_s_std_internal(dev, NULL, std);
394d73f822ce775e004836ffc01ce9feae27d0d65cfPete Eberlein	}
395d73f822ce775e004836ffc01ce9feae27d0d65cfPete Eberlein	case VIDIOC_G_STD:
396d73f822ce775e004836ffc01ce9feae27d0d65cfPete Eberlein	{
397d73f822ce775e004836ffc01ce9feae27d0d65cfPete Eberlein		v4l2_std_id *std = arg;
398d73f822ce775e004836ffc01ce9feae27d0d65cfPete Eberlein		*std = dev->tvnorm->id;
399d73f822ce775e004836ffc01ce9feae27d0d65cfPete Eberlein		return 0;
400d73f822ce775e004836ffc01ce9feae27d0d65cfPete Eberlein	}
401d73f822ce775e004836ffc01ce9feae27d0d65cfPete Eberlein	case VIDIOC_QUERYCTRL:
402d73f822ce775e004836ffc01ce9feae27d0d65cfPete Eberlein	{
403d73f822ce775e004836ffc01ce9feae27d0d65cfPete Eberlein		struct v4l2_queryctrl *ctrl = arg;
404d73f822ce775e004836ffc01ce9feae27d0d65cfPete Eberlein		if (V4L2_CTRL_ID2CLASS(ctrl->id) == V4L2_CTRL_CLASS_USER)
405d73f822ce775e004836ffc01ce9feae27d0d65cfPete Eberlein			return saa7134_queryctrl(NULL, NULL, ctrl);
406d73f822ce775e004836ffc01ce9feae27d0d65cfPete Eberlein	}
407d73f822ce775e004836ffc01ce9feae27d0d65cfPete Eberlein	case VIDIOC_G_CTRL:
408d73f822ce775e004836ffc01ce9feae27d0d65cfPete Eberlein	{
409d73f822ce775e004836ffc01ce9feae27d0d65cfPete Eberlein		struct v4l2_control *ctrl = arg;
410d73f822ce775e004836ffc01ce9feae27d0d65cfPete Eberlein		if (V4L2_CTRL_ID2CLASS(ctrl->id) == V4L2_CTRL_CLASS_USER)
411d73f822ce775e004836ffc01ce9feae27d0d65cfPete Eberlein			return saa7134_g_ctrl_internal(dev, NULL, ctrl);
412d73f822ce775e004836ffc01ce9feae27d0d65cfPete Eberlein	}
413d73f822ce775e004836ffc01ce9feae27d0d65cfPete Eberlein	case VIDIOC_S_CTRL:
414d73f822ce775e004836ffc01ce9feae27d0d65cfPete Eberlein	{
415d73f822ce775e004836ffc01ce9feae27d0d65cfPete Eberlein		struct v4l2_control *ctrl = arg;
416d73f822ce775e004836ffc01ce9feae27d0d65cfPete Eberlein		if (V4L2_CTRL_ID2CLASS(ctrl->id) == V4L2_CTRL_CLASS_USER)
417d73f822ce775e004836ffc01ce9feae27d0d65cfPete Eberlein			return saa7134_s_ctrl_internal(dev, NULL, ctrl);
418d73f822ce775e004836ffc01ce9feae27d0d65cfPete Eberlein	}
419d73f822ce775e004836ffc01ce9feae27d0d65cfPete Eberlein	}
420d73f822ce775e004836ffc01ce9feae27d0d65cfPete Eberlein	return -EINVAL;
421d73f822ce775e004836ffc01ce9feae27d0d65cfPete Eberlein
422d73f822ce775e004836ffc01ce9feae27d0d65cfPete Eberlein}
423d73f822ce775e004836ffc01ce9feae27d0d65cfPete Eberlein
424866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartmanstatic struct go7007_hpi_ops saa7134_go7007_hpi_ops = {
425866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman	.interface_reset	= saa7134_go7007_interface_reset,
426866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman	.write_interrupt	= saa7134_go7007_write_interrupt,
427866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman	.read_interrupt		= saa7134_go7007_read_interrupt,
428866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman	.stream_start		= saa7134_go7007_stream_start,
429866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman	.stream_stop		= saa7134_go7007_stream_stop,
430866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman	.send_firmware		= saa7134_go7007_send_firmware,
431d73f822ce775e004836ffc01ce9feae27d0d65cfPete Eberlein	.send_command		= saa7134_go7007_send_command,
432866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman};
433866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman
434866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman/********************* Add/remove functions *********************/
435866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman
436866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartmanstatic int saa7134_go7007_init(struct saa7134_dev *dev)
437866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman{
438866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman	struct go7007 *go;
439866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman	struct saa7134_go7007 *saa;
440866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman
441866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman	printk(KERN_DEBUG "saa7134-go7007: probing new SAA713X board\n");
442866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman
4437a6cb0d5497418599d2125b670926b75e673861cJulia Lawall	saa = kzalloc(sizeof(struct saa7134_go7007), GFP_KERNEL);
444866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman	if (saa == NULL)
445866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman		return -ENOMEM;
446866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman
447866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman	/* Allocate a couple pages for receiving the compressed stream */
448866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman	saa->top = (u8 *)get_zeroed_page(GFP_KERNEL);
449866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman	if (!saa->top)
450866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman		goto allocfail;
451866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman	saa->bottom = (u8 *)get_zeroed_page(GFP_KERNEL);
452866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman	if (!saa->bottom)
453866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman		goto allocfail;
454866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman
455866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman	go = go7007_alloc(&board_voyager, &dev->pci->dev);
456866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman	if (go == NULL)
457866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman		goto allocfail;
458866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman	go->board_id = GO7007_BOARDID_PCI_VOYAGER;
459866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman	strncpy(go->name, saa7134_boards[dev->board].name, sizeof(go->name));
460866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman	go->hpi_ops = &saa7134_go7007_hpi_ops;
461866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman	go->hpi_context = saa;
462866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman	saa->dev = dev;
463866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman
464866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman	/* Boot the GO7007 */
465866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman	if (go7007_boot_encoder(go, go->board_info->flags &
466866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman					GO7007_BOARD_USE_ONBOARD_I2C) < 0)
467866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman		goto initfail;
468866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman
469866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman	/* Do any final GO7007 initialization, then register the
470866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman	 * V4L2 and ALSA interfaces */
471866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman	if (go7007_register_encoder(go) < 0)
472866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman		goto initfail;
473866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman	dev->empress_dev = go->video_dev;
474866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman	video_set_drvdata(dev->empress_dev, go);
475866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman
476866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman	go->status = STATUS_ONLINE;
477866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman	return 0;
478866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman
479866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartmaninitfail:
480866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman	go->status = STATUS_SHUTDOWN;
481866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman	return 0;
482866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman
483866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartmanallocfail:
484866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman	if (saa->top)
485866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman		free_page((unsigned long)saa->top);
486866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman	if (saa->bottom)
487866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman		free_page((unsigned long)saa->bottom);
488866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman	kfree(saa);
489866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman	return -ENOMEM;
490866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman}
491866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman
492866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartmanstatic int saa7134_go7007_fini(struct saa7134_dev *dev)
493866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman{
494866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman	struct go7007 *go;
495866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman	struct saa7134_go7007 *saa;
496866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman
497866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman	if (NULL == dev->empress_dev)
498866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman		return 0;
499866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman
500866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman	go = video_get_drvdata(dev->empress_dev);
501866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman	saa = go->hpi_context;
502866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman	go->status = STATUS_SHUTDOWN;
503866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman	free_page((unsigned long)saa->top);
504866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman	free_page((unsigned long)saa->bottom);
505866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman	kfree(saa);
506866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman	go7007_remove(go);
507866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman	dev->empress_dev = NULL;
508866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman
509866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman	return 0;
510866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman}
511866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman
512866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartmanstatic struct saa7134_mpeg_ops saa7134_go7007_ops = {
513866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman	.type          = SAA7134_MPEG_GO7007,
514866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman	.init          = saa7134_go7007_init,
515866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman	.fini          = saa7134_go7007_fini,
516866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman	.irq_ts_done   = saa7134_go7007_irq_ts_done,
517866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman};
518866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman
519866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartmanstatic int __init saa7134_go7007_mod_init(void)
520866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman{
521866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman	return saa7134_ts_register(&saa7134_go7007_ops);
522866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman}
523866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman
524866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartmanstatic void __exit saa7134_go7007_mod_cleanup(void)
525866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman{
526866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman	saa7134_ts_unregister(&saa7134_go7007_ops);
527866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman}
528866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman
529866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartmanmodule_init(saa7134_go7007_mod_init);
530866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartmanmodule_exit(saa7134_go7007_mod_cleanup);
531866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman
532866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-HartmanMODULE_LICENSE("GPL v2");
533