--- zzzz-none-000/linux-3.10.107/drivers/media/platform/omap3isp/isphist.c 2017-06-27 09:49:32.000000000 +0000 +++ scorpion-7490-727/linux-3.10.107/drivers/media/platform/omap3isp/isphist.c 2021-02-04 17:41:59.000000000 +0000 @@ -13,33 +13,21 @@ * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA */ #include +#include +#include +#include #include #include -#include #include "isp.h" #include "ispreg.h" #include "isphist.h" -#define OMAP24XX_DMA_NO_DEVICE 0 - #define HIST_CONFIG_DMA 1 -#define HIST_USING_DMA(hist) ((hist)->dma_ch >= 0) - /* * hist_reset_mem - clear Histogram memory before start stats engine. */ @@ -72,20 +60,6 @@ hist->wait_acc_frames = conf->num_acc_frames; } -static void hist_dma_config(struct ispstat *hist) -{ - struct isp_device *isp = hist->isp; - - hist->dma_config.data_type = OMAP_DMA_DATA_TYPE_S32; - hist->dma_config.sync_mode = OMAP_DMA_SYNC_ELEMENT; - hist->dma_config.frame_count = 1; - hist->dma_config.src_amode = OMAP_DMA_AMODE_CONSTANT; - hist->dma_config.src_start = isp->mmio_base_phys[OMAP3_ISP_IOMEM_HIST] - + ISPHIST_DATA; - hist->dma_config.dst_amode = OMAP_DMA_AMODE_POST_INC; - hist->dma_config.src_or_dst_synch = OMAP_DMA_SRC_SYNC; -} - /* * hist_setup_regs - Helper function to update Histogram registers. */ @@ -186,17 +160,12 @@ & ISPHIST_PCR_BUSY; } -static void hist_dma_cb(int lch, u16 ch_status, void *data) +static void hist_dma_cb(void *data) { struct ispstat *hist = data; - if (ch_status & ~OMAP_DMA_BLOCK_IRQ) { - dev_dbg(hist->isp->dev, "hist: DMA error. status = 0x%04x\n", - ch_status); - omap_stop_dma(lch); - hist_reset_mem(hist); - atomic_set(&hist->buf_err, 1); - } + /* FIXME: The DMA engine API can't report transfer errors :-/ */ + isp_reg_clr(hist->isp, OMAP3_ISP_IOMEM_HIST, ISPHIST_CNT, ISPHIST_CNT_CLEAR); @@ -208,24 +177,57 @@ static int hist_buf_dma(struct ispstat *hist) { dma_addr_t dma_addr = hist->active_buf->dma_addr; + struct dma_async_tx_descriptor *tx; + struct dma_slave_config cfg; + dma_cookie_t cookie; + int ret; if (unlikely(!dma_addr)) { dev_dbg(hist->isp->dev, "hist: invalid DMA buffer address\n"); - hist_reset_mem(hist); - return STAT_NO_BUF; + goto error; } isp_reg_writel(hist->isp, 0, OMAP3_ISP_IOMEM_HIST, ISPHIST_ADDR); isp_reg_set(hist->isp, OMAP3_ISP_IOMEM_HIST, ISPHIST_CNT, ISPHIST_CNT_CLEAR); omap3isp_flush(hist->isp); - hist->dma_config.dst_start = dma_addr; - hist->dma_config.elem_count = hist->buf_size / sizeof(u32); - omap_set_dma_params(hist->dma_ch, &hist->dma_config); - omap_start_dma(hist->dma_ch); + memset(&cfg, 0, sizeof(cfg)); + cfg.src_addr = hist->isp->mmio_hist_base_phys + ISPHIST_DATA; + cfg.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; + cfg.src_maxburst = hist->buf_size / 4; + + ret = dmaengine_slave_config(hist->dma_ch, &cfg); + if (ret < 0) { + dev_dbg(hist->isp->dev, + "hist: DMA slave configuration failed\n"); + goto error; + } + + tx = dmaengine_prep_slave_single(hist->dma_ch, dma_addr, + hist->buf_size, DMA_DEV_TO_MEM, + DMA_CTRL_ACK); + if (tx == NULL) { + dev_dbg(hist->isp->dev, + "hist: DMA slave preparation failed\n"); + goto error; + } + + tx->callback = hist_dma_cb; + tx->callback_param = hist; + cookie = tx->tx_submit(tx); + if (dma_submit_error(cookie)) { + dev_dbg(hist->isp->dev, "hist: DMA submission failed\n"); + goto error; + } + + dma_async_issue_pending(hist->dma_ch); return STAT_BUF_WAITING_DMA; + +error: + hist_reset_mem(hist); + return STAT_NO_BUF; } static int hist_buf_pio(struct ispstat *hist) @@ -282,7 +284,7 @@ if (--(hist->wait_acc_frames)) return STAT_NO_BUF; - if (HIST_USING_DMA(hist)) + if (hist->dma_ch) ret = hist_buf_dma(hist); else ret = hist_buf_pio(hist); @@ -299,7 +301,7 @@ /* * hist_validate_params - Helper function to check user given params. - * @user_cfg: Pointer to user configuration structure. + * @new_conf: Pointer to user configuration structure. * * Returns 0 on success configuration. */ @@ -351,7 +353,7 @@ buf_size = hist_get_buf_size(user_cfg); if (buf_size > user_cfg->buf_size) - /* User's buf_size request wasn't enoght */ + /* User's buf_size request wasn't enough */ user_cfg->buf_size = buf_size; else if (user_cfg->buf_size > OMAP3ISP_HIST_MAX_BUF_SIZE) user_cfg->buf_size = OMAP3ISP_HIST_MAX_BUF_SIZE; @@ -483,18 +485,28 @@ hist->isp = isp; - if (HIST_CONFIG_DMA) - ret = omap_request_dma(OMAP24XX_DMA_NO_DEVICE, "DMA_ISP_HIST", - hist_dma_cb, hist, &hist->dma_ch); - if (ret) { - if (HIST_CONFIG_DMA) - dev_warn(isp->dev, "hist: DMA request channel failed. " - "Using PIO only.\n"); - hist->dma_ch = -1; - } else { - dev_dbg(isp->dev, "hist: DMA channel = %d\n", hist->dma_ch); - hist_dma_config(hist); - omap_enable_dma_irq(hist->dma_ch, OMAP_DMA_BLOCK_IRQ); + if (HIST_CONFIG_DMA) { + struct platform_device *pdev = to_platform_device(isp->dev); + struct resource *res; + unsigned int sig = 0; + dma_cap_mask_t mask; + + dma_cap_zero(mask); + dma_cap_set(DMA_SLAVE, mask); + + res = platform_get_resource_byname(pdev, IORESOURCE_DMA, + "hist"); + if (res) + sig = res->start; + + hist->dma_ch = dma_request_slave_channel_compat(mask, + omap_dma_filter_fn, &sig, isp->dev, "hist"); + if (!hist->dma_ch) + dev_warn(isp->dev, + "hist: DMA channel request failed, using PIO\n"); + else + dev_dbg(isp->dev, "hist: using DMA channel %s\n", + dma_chan_name(hist->dma_ch)); } hist->ops = &hist_ops; @@ -503,8 +515,8 @@ ret = omap3isp_stat_init(hist, "histogram", &hist_subdev_ops); if (ret) { - if (HIST_USING_DMA(hist)) - omap_free_dma(hist->dma_ch); + if (hist->dma_ch) + dma_release_channel(hist->dma_ch); } return ret; @@ -515,7 +527,10 @@ */ void omap3isp_hist_cleanup(struct isp_device *isp) { - if (HIST_USING_DMA(&isp->isp_hist)) - omap_free_dma(isp->isp_hist.dma_ch); - omap3isp_stat_cleanup(&isp->isp_hist); + struct ispstat *hist = &isp->isp_hist; + + if (hist->dma_ch) + dma_release_channel(hist->dma_ch); + + omap3isp_stat_cleanup(hist); }