mirror of
https://gitee.com/openharmony/kernel_linux
synced 2025-01-07 16:33:34 +00:00
V4L/DVB (6329): Additional Fixes for saa7134 suspend/resume
Fixes few more problems I found in my saa7134 resume code: * Race between IRQ handler and .suspend()/.resume() functions * Removes timeout timers on active buffers - those buffers will be recaptured after resume * Adds suspend/resume for IR code - probably necessary if using polling mode * Adds #ifdef CONFIG_PM overs suspend code * Runs a quirk in set_tvnorm in suspend/resume too * Rearranges the order of calls in saa7134_resume to be exactly as in saa7134_initdev thus the card is initialized in exactly the same way * Since DMA audio capture suspend/resume isn't yet supported, avoid re-enabling it on resume for now Signed-off-by: Maxim Levitsky <maximlevitsky@gmail.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>
This commit is contained in:
parent
7e7f05ca15
commit
c458473ebf
@ -429,7 +429,7 @@ int saa7134_set_dmabits(struct saa7134_dev *dev)
|
|||||||
|
|
||||||
assert_spin_locked(&dev->slock);
|
assert_spin_locked(&dev->slock);
|
||||||
|
|
||||||
if (dev->inresume)
|
if (dev->insuspend)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/* video capture -- dma 0 + video task A */
|
/* video capture -- dma 0 + video task A */
|
||||||
@ -563,6 +563,9 @@ static irqreturn_t saa7134_irq(int irq, void *dev_id)
|
|||||||
unsigned long report,status;
|
unsigned long report,status;
|
||||||
int loop, handled = 0;
|
int loop, handled = 0;
|
||||||
|
|
||||||
|
if (dev->insuspend)
|
||||||
|
goto out;
|
||||||
|
|
||||||
for (loop = 0; loop < 10; loop++) {
|
for (loop = 0; loop < 10; loop++) {
|
||||||
report = saa_readl(SAA7134_IRQ_REPORT);
|
report = saa_readl(SAA7134_IRQ_REPORT);
|
||||||
status = saa_readl(SAA7134_IRQ_STATUS);
|
status = saa_readl(SAA7134_IRQ_STATUS);
|
||||||
@ -1163,6 +1166,7 @@ static void __devexit saa7134_finidev(struct pci_dev *pci_dev)
|
|||||||
kfree(dev);
|
kfree(dev);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_PM
|
||||||
static int saa7134_suspend(struct pci_dev *pci_dev , pm_message_t state)
|
static int saa7134_suspend(struct pci_dev *pci_dev , pm_message_t state)
|
||||||
{
|
{
|
||||||
|
|
||||||
@ -1176,6 +1180,17 @@ static int saa7134_suspend(struct pci_dev *pci_dev , pm_message_t state)
|
|||||||
saa_writel(SAA7134_IRQ2, 0);
|
saa_writel(SAA7134_IRQ2, 0);
|
||||||
saa_writel(SAA7134_MAIN_CTRL, 0);
|
saa_writel(SAA7134_MAIN_CTRL, 0);
|
||||||
|
|
||||||
|
synchronize_irq(pci_dev->irq);
|
||||||
|
dev->insuspend = 1;
|
||||||
|
|
||||||
|
/* Disable timeout timers - if we have active buffers, we will
|
||||||
|
fill them on resume*/
|
||||||
|
|
||||||
|
del_timer(&dev->video_q.timeout);
|
||||||
|
del_timer(&dev->vbi_q.timeout);
|
||||||
|
del_timer(&dev->ts_q.timeout);
|
||||||
|
saa7134_ir_stop(dev);
|
||||||
|
|
||||||
pci_set_power_state(pci_dev, pci_choose_state(pci_dev, state));
|
pci_set_power_state(pci_dev, pci_choose_state(pci_dev, state));
|
||||||
pci_save_state(pci_dev);
|
pci_save_state(pci_dev);
|
||||||
|
|
||||||
@ -1194,24 +1209,27 @@ static int saa7134_resume(struct pci_dev *pci_dev)
|
|||||||
/* Do things that are done in saa7134_initdev ,
|
/* Do things that are done in saa7134_initdev ,
|
||||||
except of initializing memory structures.*/
|
except of initializing memory structures.*/
|
||||||
|
|
||||||
dev->inresume = 1;
|
|
||||||
saa7134_board_init1(dev);
|
saa7134_board_init1(dev);
|
||||||
|
|
||||||
|
/* saa7134_hwinit1 */
|
||||||
if (saa7134_boards[dev->board].video_out)
|
if (saa7134_boards[dev->board].video_out)
|
||||||
saa7134_videoport_init(dev);
|
saa7134_videoport_init(dev);
|
||||||
|
|
||||||
if (card_has_mpeg(dev))
|
if (card_has_mpeg(dev))
|
||||||
saa7134_ts_init_hw(dev);
|
saa7134_ts_init_hw(dev);
|
||||||
|
if (dev->remote)
|
||||||
|
saa7134_ir_start(dev, dev->remote);
|
||||||
saa7134_hw_enable1(dev);
|
saa7134_hw_enable1(dev);
|
||||||
saa7134_set_decoder(dev);
|
|
||||||
saa7134_i2c_call_clients(dev, VIDIOC_S_STD, &dev->tvnorm->id);
|
|
||||||
saa7134_board_init2(dev);
|
|
||||||
saa7134_hw_enable2(dev);
|
|
||||||
|
|
||||||
|
|
||||||
|
saa7134_board_init2(dev);
|
||||||
|
|
||||||
|
/*saa7134_hwinit2*/
|
||||||
|
saa7134_set_tvnorm_hw(dev);
|
||||||
saa7134_tvaudio_setmute(dev);
|
saa7134_tvaudio_setmute(dev);
|
||||||
saa7134_tvaudio_setvolume(dev, dev->ctl_volume);
|
saa7134_tvaudio_setvolume(dev, dev->ctl_volume);
|
||||||
|
saa7134_tvaudio_do_scan(dev);
|
||||||
saa7134_enable_i2s(dev);
|
saa7134_enable_i2s(dev);
|
||||||
|
saa7134_hw_enable2(dev);
|
||||||
|
|
||||||
/*resume unfinished buffer(s)*/
|
/*resume unfinished buffer(s)*/
|
||||||
spin_lock_irqsave(&dev->slock, flags);
|
spin_lock_irqsave(&dev->slock, flags);
|
||||||
@ -1219,13 +1237,19 @@ static int saa7134_resume(struct pci_dev *pci_dev)
|
|||||||
saa7134_buffer_requeue(dev, &dev->vbi_q);
|
saa7134_buffer_requeue(dev, &dev->vbi_q);
|
||||||
saa7134_buffer_requeue(dev, &dev->ts_q);
|
saa7134_buffer_requeue(dev, &dev->ts_q);
|
||||||
|
|
||||||
|
/* FIXME: Disable DMA audio sound - temporary till proper support
|
||||||
|
is implemented*/
|
||||||
|
|
||||||
|
dev->dmasound.dma_running = 0;
|
||||||
|
|
||||||
/* start DMA now*/
|
/* start DMA now*/
|
||||||
dev->inresume = 0;
|
dev->insuspend = 0;
|
||||||
saa7134_set_dmabits(dev);
|
saa7134_set_dmabits(dev);
|
||||||
spin_unlock_irqrestore(&dev->slock, flags);
|
spin_unlock_irqrestore(&dev->slock, flags);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/* ----------------------------------------------------------- */
|
/* ----------------------------------------------------------- */
|
||||||
|
|
||||||
@ -1262,8 +1286,10 @@ static struct pci_driver saa7134_pci_driver = {
|
|||||||
.id_table = saa7134_pci_tbl,
|
.id_table = saa7134_pci_tbl,
|
||||||
.probe = saa7134_initdev,
|
.probe = saa7134_initdev,
|
||||||
.remove = __devexit_p(saa7134_finidev),
|
.remove = __devexit_p(saa7134_finidev),
|
||||||
|
#ifdef CONFIG_PM
|
||||||
.suspend = saa7134_suspend,
|
.suspend = saa7134_suspend,
|
||||||
.resume = saa7134_resume
|
.resume = saa7134_resume
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
static int saa7134_init(void)
|
static int saa7134_init(void)
|
||||||
|
@ -159,7 +159,7 @@ static void saa7134_input_timer(unsigned long data)
|
|||||||
mod_timer(&ir->timer, jiffies + msecs_to_jiffies(ir->polling));
|
mod_timer(&ir->timer, jiffies + msecs_to_jiffies(ir->polling));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void saa7134_ir_start(struct saa7134_dev *dev, struct card_ir *ir)
|
void saa7134_ir_start(struct saa7134_dev *dev, struct card_ir *ir)
|
||||||
{
|
{
|
||||||
if (ir->polling) {
|
if (ir->polling) {
|
||||||
setup_timer(&ir->timer, saa7134_input_timer,
|
setup_timer(&ir->timer, saa7134_input_timer,
|
||||||
@ -182,7 +182,7 @@ static void saa7134_ir_start(struct saa7134_dev *dev, struct card_ir *ir)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void saa7134_ir_stop(struct saa7134_dev *dev)
|
void saa7134_ir_stop(struct saa7134_dev *dev)
|
||||||
{
|
{
|
||||||
if (dev->remote->polling)
|
if (dev->remote->polling)
|
||||||
del_timer_sync(&dev->remote->timer);
|
del_timer_sync(&dev->remote->timer);
|
||||||
|
@ -231,7 +231,7 @@ static void mute_input_7134(struct saa7134_dev *dev)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (dev->hw_mute == mute &&
|
if (dev->hw_mute == mute &&
|
||||||
dev->hw_input == in && !dev->inresume) {
|
dev->hw_input == in && !dev->insuspend) {
|
||||||
dprintk("mute/input: nothing to do [mute=%d,input=%s]\n",
|
dprintk("mute/input: nothing to do [mute=%d,input=%s]\n",
|
||||||
mute,in->name);
|
mute,in->name);
|
||||||
return;
|
return;
|
||||||
|
@ -560,15 +560,8 @@ void set_tvnorm(struct saa7134_dev *dev, struct saa7134_tvnorm *norm)
|
|||||||
|
|
||||||
dev->crop_current = dev->crop_defrect;
|
dev->crop_current = dev->crop_defrect;
|
||||||
|
|
||||||
saa7134_set_decoder(dev);
|
saa7134_set_tvnorm_hw(dev);
|
||||||
|
|
||||||
if (card_in(dev, dev->ctl_input).tv) {
|
|
||||||
if ((card(dev).tuner_type == TUNER_PHILIPS_TDA8290)
|
|
||||||
&& ((card(dev).tuner_config == 1)
|
|
||||||
|| (card(dev).tuner_config == 2)))
|
|
||||||
saa7134_set_gpio(dev, 22, 5);
|
|
||||||
saa7134_i2c_call_clients(dev, VIDIOC_S_STD, &norm->id);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void video_mux(struct saa7134_dev *dev, int input)
|
static void video_mux(struct saa7134_dev *dev, int input)
|
||||||
@ -579,7 +572,8 @@ static void video_mux(struct saa7134_dev *dev, int input)
|
|||||||
saa7134_tvaudio_setinput(dev, &card_in(dev, input));
|
saa7134_tvaudio_setinput(dev, &card_in(dev, input));
|
||||||
}
|
}
|
||||||
|
|
||||||
void saa7134_set_decoder(struct saa7134_dev *dev)
|
|
||||||
|
static void saa7134_set_decoder(struct saa7134_dev *dev)
|
||||||
{
|
{
|
||||||
int luma_control, sync_control, mux;
|
int luma_control, sync_control, mux;
|
||||||
|
|
||||||
@ -630,6 +624,19 @@ void saa7134_set_decoder(struct saa7134_dev *dev)
|
|||||||
saa_writeb(SAA7134_RAW_DATA_OFFSET, 0x80);
|
saa_writeb(SAA7134_RAW_DATA_OFFSET, 0x80);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void saa7134_set_tvnorm_hw(struct saa7134_dev *dev)
|
||||||
|
{
|
||||||
|
saa7134_set_decoder(dev);
|
||||||
|
|
||||||
|
if (card_in(dev, dev->ctl_input).tv) {
|
||||||
|
if ((card(dev).tuner_type == TUNER_PHILIPS_TDA8290)
|
||||||
|
&& ((card(dev).tuner_config == 1)
|
||||||
|
|| (card(dev).tuner_config == 2)))
|
||||||
|
saa7134_set_gpio(dev, 22, 5);
|
||||||
|
saa7134_i2c_call_clients(dev, VIDIOC_S_STD, &dev->tvnorm->id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void set_h_prescale(struct saa7134_dev *dev, int task, int prescale)
|
static void set_h_prescale(struct saa7134_dev *dev, int task, int prescale)
|
||||||
{
|
{
|
||||||
static const struct {
|
static const struct {
|
||||||
|
@ -524,7 +524,7 @@ struct saa7134_dev {
|
|||||||
unsigned int hw_mute;
|
unsigned int hw_mute;
|
||||||
int last_carrier;
|
int last_carrier;
|
||||||
int nosignal;
|
int nosignal;
|
||||||
unsigned int inresume;
|
unsigned int insuspend;
|
||||||
|
|
||||||
/* SAA7134_MPEG_* */
|
/* SAA7134_MPEG_* */
|
||||||
struct saa7134_ts ts;
|
struct saa7134_ts ts;
|
||||||
@ -632,7 +632,7 @@ extern struct video_device saa7134_radio_template;
|
|||||||
|
|
||||||
void set_tvnorm(struct saa7134_dev *dev, struct saa7134_tvnorm *norm);
|
void set_tvnorm(struct saa7134_dev *dev, struct saa7134_tvnorm *norm);
|
||||||
int saa7134_videoport_init(struct saa7134_dev *dev);
|
int saa7134_videoport_init(struct saa7134_dev *dev);
|
||||||
void saa7134_set_decoder(struct saa7134_dev *dev);
|
void saa7134_set_tvnorm_hw(struct saa7134_dev *dev);
|
||||||
|
|
||||||
int saa7134_common_ioctl(struct saa7134_dev *dev,
|
int saa7134_common_ioctl(struct saa7134_dev *dev,
|
||||||
unsigned int cmd, void *arg);
|
unsigned int cmd, void *arg);
|
||||||
@ -706,6 +706,8 @@ int saa7134_input_init1(struct saa7134_dev *dev);
|
|||||||
void saa7134_input_fini(struct saa7134_dev *dev);
|
void saa7134_input_fini(struct saa7134_dev *dev);
|
||||||
void saa7134_input_irq(struct saa7134_dev *dev);
|
void saa7134_input_irq(struct saa7134_dev *dev);
|
||||||
void saa7134_set_i2c_ir(struct saa7134_dev *dev, struct IR_i2c *ir);
|
void saa7134_set_i2c_ir(struct saa7134_dev *dev, struct IR_i2c *ir);
|
||||||
|
void saa7134_ir_start(struct saa7134_dev *dev, struct card_ir *ir);
|
||||||
|
void saa7134_ir_stop(struct saa7134_dev *dev);
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
Loading…
Reference in New Issue
Block a user