diff options
-rw-r--r-- | drivers/mxc/asrc/mxc_asrc.c | 23 | ||||
-rw-r--r-- | include/linux/mxc_asrc.h | 3 |
2 files changed, 22 insertions, 4 deletions
diff --git a/drivers/mxc/asrc/mxc_asrc.c b/drivers/mxc/asrc/mxc_asrc.c index dbf3fffcb100..0a3860afc986 100644 --- a/drivers/mxc/asrc/mxc_asrc.c +++ b/drivers/mxc/asrc/mxc_asrc.c @@ -51,6 +51,7 @@ static struct class *asrc_class; DEFINE_SPINLOCK(data_lock); DEFINE_SPINLOCK(input_int_lock); DEFINE_SPINLOCK(output_int_lock); +DEFINE_SPINLOCK(asrc_clock_lock); #define AICPA 0 /* Input Clock Divider A Offset */ #define AICDA 3 /* Input Clock Prescaler A Offset */ @@ -609,7 +610,6 @@ void asrc_start_conv(enum asrc_pair_index index) reg = __raw_readl(asrc_vrt_base_addr + ASRC_ASRCTR_REG); if ((reg & 0x0E) == 0) clk_enable(mxc_asrc_data->asrc_audio_clk); - reg |= (1 << (1 + index)); __raw_writel(reg, asrc_vrt_base_addr + ASRC_ASRCTR_REG); @@ -1399,7 +1399,6 @@ static long asrc_ioctl(struct file *file, err = -EFAULT; break; } - spin_lock_irqsave(&input_int_lock, lock_flags); if (params->input_queue_empty == 0) { err = -EFAULT; @@ -1524,6 +1523,13 @@ static int mxc_asrc_open(struct inode *inode, struct file *file) { int err = 0; struct asrc_pair_params *pair_params; + unsigned long lock_flags; + + spin_lock_irqsave(&asrc_clock_lock, lock_flags); + g_asrc_data->counter++; + clk_enable(mxc_asrc_data->asrc_core_clk); + spin_unlock_irqrestore(&asrc_clock_lock, lock_flags); + if (signal_pending(current)) return -EINTR; pair_params = kzalloc(sizeof(struct asrc_pair_params), GFP_KERNEL); @@ -1548,7 +1554,9 @@ static int mxc_asrc_open(struct inode *inode, struct file *file) static int mxc_asrc_close(struct inode *inode, struct file *file) { struct asrc_pair_params *pair_params; + unsigned long lock_flags; pair_params = file->private_data; + if (pair_params->asrc_active == 1) { dmaengine_terminate_all(pair_params->input_dma_channel); dmaengine_terminate_all(pair_params->output_dma_channel); @@ -1562,8 +1570,15 @@ static int mxc_asrc_close(struct inode *inode, struct file *file) mxc_free_dma_buf(pair_params); asrc_release_pair(pair_params->index); } + kfree(pair_params); file->private_data = NULL; + + spin_lock_irqsave(&asrc_clock_lock, lock_flags); + g_asrc_data->counter--; + if (g_asrc_data->counter == 0) + clk_disable(mxc_asrc_data->asrc_core_clk); + spin_unlock_irqrestore(&asrc_clock_lock, lock_flags); return 0; } @@ -1713,6 +1728,7 @@ static int mxc_asrc_probe(struct platform_device *pdev) g_asrc_data->asrc_pair[0].overload_error = 0; g_asrc_data->asrc_pair[1].overload_error = 0; g_asrc_data->asrc_pair[2].overload_error = 0; + g_asrc_data->counter = 0; asrc_major = register_chrdev(asrc_major, "mxc_asrc", &asrc_fops); if (asrc_major < 0) { @@ -1740,6 +1756,7 @@ static int mxc_asrc_probe(struct platform_device *pdev) mxc_asrc_data = (struct imx_asrc_platform_data *)pdev->dev.platform_data; + clk_enable(mxc_asrc_data->asrc_core_clk); switch (mxc_asrc_data->clk_map_ver) { @@ -1786,7 +1803,7 @@ static int mxc_asrc_probe(struct platform_device *pdev) err = mxc_init_asrc(); if (err < 0) goto err_out_class; - + clk_disable(mxc_asrc_data->asrc_core_clk); goto out; err_out_class: diff --git a/include/linux/mxc_asrc.h b/include/linux/mxc_asrc.h index a8d8b8bc474a..516b0b69f286 100644 --- a/include/linux/mxc_asrc.h +++ b/include/linux/mxc_asrc.h @@ -1,5 +1,5 @@ /* - * Copyright 2008-2011 Freescale Semiconductor, Inc. All Rights Reserved. + * Copyright 2008-2012 Freescale Semiconductor, Inc. All Rights Reserved. */ /* @@ -197,6 +197,7 @@ struct asrc_pair_params { struct asrc_data { struct asrc_pair asrc_pair[3]; + unsigned int counter; }; extern int asrc_req_pair(int chn_num, enum asrc_pair_index *index); |