diff options
Diffstat (limited to 'drivers/gpu/imx/dcss/dcss-hdr10.c')
-rw-r--r-- | drivers/gpu/imx/dcss/dcss-hdr10.c | 656 |
1 files changed, 656 insertions, 0 deletions
diff --git a/drivers/gpu/imx/dcss/dcss-hdr10.c b/drivers/gpu/imx/dcss/dcss-hdr10.c new file mode 100644 index 000000000000..d5888936034f --- /dev/null +++ b/drivers/gpu/imx/dcss/dcss-hdr10.c @@ -0,0 +1,656 @@ +/* + * Copyright (C) 2017 NXP + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * 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. + */ + +#include <linux/device.h> +#include <linux/bitops.h> +#include <linux/io.h> +#include <linux/firmware.h> +#include <drm/drm_fourcc.h> + +#include <video/imx-dcss.h> +#include "dcss-prv.h" + +#define USE_TBL_HEADER + +#ifdef USE_TBL_HEADER +#include "dcss-hdr10-tables.h" +#endif + +#define USE_CTXLD + +#define DCSS_HDR10_A0_LUT 0x0000 +#define DCSS_HDR10_A1_LUT 0x1000 +#define DCSS_HDR10_A2_LUT 0x2000 +/* one CSCA and CSCB for each channel(pipe) */ +#define DCSS_HDR10_CSCA_BASE 0x3000 +#define DCSS_HDR10_CSCB_BASE 0x3800 + +/* one CSCO for all channels(pipes) */ +#define DCSS_HDR10_CSCO_BASE 0x3000 + +#define DCSS_HDR10_LUT_CONTROL (DCSS_HDR10_CSCA_BASE + 0x80) +#define LUT_ENABLE BIT(0) +#define LUT_EN_FOR_ALL_PELS BIT(1) +#define LUT_BYPASS BIT(15) +#define DCSS_HDR10_FL2FX (DCSS_HDR10_CSCB_BASE + 0x74) +#define DCSS_HDR10_LTNL (DCSS_HDR10_CSCO_BASE + 0x74) +#define LTNL_PASS_THRU BIT(0) +#define FIX2FLT_DISABLE BIT(1) +#define LTNL_EN_FOR_ALL_PELS BIT(2) +#define FIX2FLT_EN_FOR_ALL_PELS BIT(3) + +/* following offsets are relative to CSC(A|B|O)_BASE */ +#define DCSS_HDR10_CSC_CONTROL 0x00 +#define CSC_EN BIT(0) +#define CSC_ALL_PIX_EN BIT(1) +#define CSC_BYPASS BIT(15) +#define DCSS_HDR10_CSC_H00 0x04 +#define DCSS_HDR10_CSC_H10 0x08 +#define DCSS_HDR10_CSC_H20 0x0C +#define DCSS_HDR10_CSC_H01 0x10 +#define DCSS_HDR10_CSC_H11 0x14 +#define DCSS_HDR10_CSC_H21 0x18 +#define DCSS_HDR10_CSC_H02 0x1C +#define DCSS_HDR10_CSC_H12 0x20 +#define DCSS_HDR10_CSC_H22 0x24 +#define H_COEF_MASK GENMASK(15, 0) +#define DCSS_HDR10_CSC_IO0 0x28 +#define DCSS_HDR10_CSC_IO1 0x2C +#define DCSS_HDR10_CSC_IO2 0x30 +#define PRE_OFFSET_MASK GENMASK(9, 0) +#define DCSS_HDR10_CSC_IO_MIN0 0x34 +#define DCSS_HDR10_CSC_IO_MIN1 0x38 +#define DCSS_HDR10_CSC_IO_MIN2 0x3C +#define DCSS_HDR10_CSC_IO_MAX0 0x40 +#define DCSS_HDR10_CSC_IO_MAX1 0x44 +#define DCSS_HDR10_CSC_IO_MAX2 0x48 +#define IO_CLIP_MASK GENMASK(9, 0) +#define DCSS_HDR10_CSC_NORM 0x4C +#define NORM_MASK GENMASK(4, 0) +#define DCSS_HDR10_CSC_OO0 0x50 +#define DCSS_HDR10_CSC_OO1 0x54 +#define DCSS_HDR10_CSC_OO2 0x58 +#define POST_OFFSET_MASK GENMASK(27, 0) +#define DCSS_HDR10_CSC_OMIN0 0x5C +#define DCSS_HDR10_CSC_OMIN1 0x60 +#define DCSS_HDR10_CSC_OMIN2 0x64 +#define DCSS_HDR10_CSC_OMAX0 0x68 +#define DCSS_HDR10_CSC_OMAX1 0x6C +#define DCSS_HDR10_CSC_OMAX2 0x70 +#define POST_CLIP_MASK GENMASK(9, 0) + +#define HDR10_IPIPE_LUT_MAX_ENTRIES 1024 +#define HDR10_OPIPE_LUT_MAX_ENTRIES 1023 +#define HDR10_CSC_MAX_REGS 29 + +#define OPIPE_CH_NO 3 + +/* Pipe config descriptor */ + +/* bits per component */ +#define HDR10_BPC_POS 0 +#define HDR10_BPC_MASK GENMASK(1, 0) +/* colorspace */ +#define HDR10_CS_POS 2 +#define HDR10_CS_MASK GENMASK(3, 2) +/* nonlinearity type */ +#define HDR10_NL_POS 4 +#define HDR10_NL_MASK GENMASK(8, 4) +/* pixel range */ +#define HDR10_PR_POS 9 +#define HDR10_PR_MASK GENMASK(10, 9) +/* gamut type */ +#define HDR10_G_POS 11 +#define HDR10_G_MASK GENMASK(15, 11) + +/* FW Table Descriptor */ +#define HDR10_TT_LUT BIT(0) +#define HDR10_TT_CSCA BIT(1) +#define HDR10_TT_CSCB BIT(2) +/* Pipe type */ +#define HDR10_PT_OUTPUT BIT(3) +/* Output pipe config descriptor */ +#define HDR10_IPIPE_DESC_POS 4 +#define HDR10_IPIPE_DESC_MASK GENMASK(19, 4) +/* Input pipe config descriptor */ +#define HDR10_OPIPE_DESC_POS 20 +#define HDR10_OPIPE_DESC_MASK GENMASK(35, 20) + +/* config invalid */ +#define HDR10_DESC_INVALID BIT(63) + +enum dcss_hdr10_csc { + HDR10_CSCA, + HDR10_CSCB, +}; + +struct dcss_hdr10_tbl_node { + u64 tbl_descriptor; + u32 *tbl_data; + + struct list_head node; +}; + +struct dcss_hdr10_opipe_tbls { + struct list_head lut; + struct list_head csc; +}; + +struct dcss_hdr10_ipipe_tbls { + struct list_head lut; + struct list_head csca; + struct list_head cscb; +}; + +struct dcss_hdr10_ch { + void __iomem *base_reg; + u32 base_ofs; + + u32 ctx_id; + + u64 old_cfg_desc; +}; + +struct dcss_hdr10_priv { + struct dcss_soc *dcss; + + struct dcss_hdr10_ch ch[4]; /* 4th channel is, actually, OPIPE */ + + struct dcss_hdr10_ipipe_tbls *ipipe_tbls; + struct dcss_hdr10_opipe_tbls *opipe_tbls; + + u8 *fw_data; + u32 fw_size; +}; + +static struct dcss_debug_reg hdr10_debug_reg[] = { + DCSS_DBG_REG(DCSS_HDR10_CSC_CONTROL), + DCSS_DBG_REG(DCSS_HDR10_CSC_H00), + DCSS_DBG_REG(DCSS_HDR10_CSC_H10), + DCSS_DBG_REG(DCSS_HDR10_CSC_H20), + DCSS_DBG_REG(DCSS_HDR10_CSC_H01), + DCSS_DBG_REG(DCSS_HDR10_CSC_H11), + DCSS_DBG_REG(DCSS_HDR10_CSC_H21), + DCSS_DBG_REG(DCSS_HDR10_CSC_H02), + DCSS_DBG_REG(DCSS_HDR10_CSC_H12), + DCSS_DBG_REG(DCSS_HDR10_CSC_H22), + DCSS_DBG_REG(DCSS_HDR10_CSC_IO0), + DCSS_DBG_REG(DCSS_HDR10_CSC_IO1), + DCSS_DBG_REG(DCSS_HDR10_CSC_IO2), + DCSS_DBG_REG(DCSS_HDR10_CSC_IO_MIN0), + DCSS_DBG_REG(DCSS_HDR10_CSC_IO_MIN1), + DCSS_DBG_REG(DCSS_HDR10_CSC_IO_MIN2), + DCSS_DBG_REG(DCSS_HDR10_CSC_IO_MAX0), + DCSS_DBG_REG(DCSS_HDR10_CSC_IO_MAX1), + DCSS_DBG_REG(DCSS_HDR10_CSC_IO_MAX2), + DCSS_DBG_REG(DCSS_HDR10_CSC_NORM), + DCSS_DBG_REG(DCSS_HDR10_CSC_OO0), + DCSS_DBG_REG(DCSS_HDR10_CSC_OO1), + DCSS_DBG_REG(DCSS_HDR10_CSC_OO2), + DCSS_DBG_REG(DCSS_HDR10_CSC_OMIN0), + DCSS_DBG_REG(DCSS_HDR10_CSC_OMIN1), + DCSS_DBG_REG(DCSS_HDR10_CSC_OMIN2), + DCSS_DBG_REG(DCSS_HDR10_CSC_OMAX0), + DCSS_DBG_REG(DCSS_HDR10_CSC_OMAX1), + DCSS_DBG_REG(DCSS_HDR10_CSC_OMAX2), +}; + +static void dcss_hdr10_write(struct dcss_soc *dcss, u32 ch_num, + u32 val, u32 ofs) +{ + struct dcss_hdr10_priv *hdr10 = dcss->hdr10_priv; + +#if !defined(USE_CTXLD) + dcss_writel(val, hdr10->ch[ch_num].base_reg + ofs); +#else + dcss_ctxld_write(dcss, hdr10->ch[ch_num].ctx_id, val, + hdr10->ch[ch_num].base_ofs + ofs); +#endif +} + +#ifdef CONFIG_DEBUG_FS +void dcss_hdr10_dump_regs(struct seq_file *s, void *data) +{ + struct dcss_soc *dcss = data; + int ch, csc, r; + int csc_no; + + for (ch = 0; ch < 4; ch++) { + void __iomem *csc_base = dcss->hdr10_priv->ch[ch].base_reg + + DCSS_HDR10_CSCA_BASE; + + if (ch < 3) { + seq_printf(s, ">> Dumping HDR10 CH %d:\n", ch); + csc_no = 2; + } else { + seq_puts(s, ">> Dumping HDR10 OPIPE:\n"); + csc_no = 1; + } + + for (csc = 0; csc < csc_no; csc++) { + csc_base += csc * 0x800; + + if (ch < 3) + seq_printf(s, "\t>> Dumping CSC%s of CH %d:\n", + csc ? "B" : "A", ch); + else + seq_puts(s, "\t>> Dumping CSC of OPIPE:\n"); + + for (r = 0; r < ARRAY_SIZE(hdr10_debug_reg); r++) + seq_printf(s, "\t%-35s(0x%04x) -> 0x%08x\n", + hdr10_debug_reg[r].name, + hdr10_debug_reg[r].ofs, + dcss_readl(csc_base + + hdr10_debug_reg[r].ofs)); + + if (csc == 0 && ch != 3) + seq_printf(s, "\t%-35s(0x%04x) -> 0x%08x\n", + "DCSS_HDR10_LUT_CONTROL", + 0x80, dcss_readl(csc_base + 0x80)); + + if (csc == 1 || ch == 3) + seq_printf(s, "\t%-35s(0x%04x) -> 0x%08x\n", + ch == 3 ? "DCSS_HDR10_LTNL" : + "DCSS_HDR10_FL2FX", + 0x74, dcss_readl(csc_base + 0x74)); + } + } +} +#endif + +static void dcss_hdr10_csc_fill(struct dcss_soc *dcss, int ch_num, + enum dcss_hdr10_csc csc_to_use, + u32 *map) +{ + int i; + u32 csc_base_ofs[] = { + DCSS_HDR10_CSCA_BASE + DCSS_HDR10_CSC_CONTROL, + DCSS_HDR10_CSCB_BASE + DCSS_HDR10_CSC_CONTROL, + }; + + for (i = 0; i < HDR10_CSC_MAX_REGS; i++) { + u32 reg_ofs = csc_base_ofs[csc_to_use] + i * sizeof(u32); + + dcss_hdr10_write(dcss, ch_num, map[i], reg_ofs); + } +} + +static void dcss_hdr10_lut_fill(struct dcss_soc *dcss, int ch_num, u32 *map) +{ + int i, comp; + u32 lut_base_ofs, ctrl_ofs, lut_entries; + + if (ch_num == OPIPE_CH_NO) { + ctrl_ofs = DCSS_HDR10_LTNL; + lut_entries = HDR10_OPIPE_LUT_MAX_ENTRIES; + } else { + ctrl_ofs = DCSS_HDR10_LUT_CONTROL; + lut_entries = HDR10_IPIPE_LUT_MAX_ENTRIES; + } + + if (ch_num != OPIPE_CH_NO) + dcss_hdr10_write(dcss, ch_num, *map++, ctrl_ofs); + + for (comp = 0; comp < 3; comp++) { + lut_base_ofs = DCSS_HDR10_A0_LUT + comp * 0x1000; + + if (ch_num == OPIPE_CH_NO) { + dcss_hdr10_write(dcss, ch_num, map[0], lut_base_ofs); + lut_base_ofs += 4; + } + + for (i = 0; i < lut_entries; i++) { + u32 reg_ofs = lut_base_ofs + i * sizeof(u32); + + dcss_hdr10_write(dcss, ch_num, map[i], reg_ofs); + } + } + + map += lut_entries; + + if (ch_num != OPIPE_CH_NO) + dcss_hdr10_write(dcss, ch_num, *map, DCSS_HDR10_FL2FX); + else + dcss_hdr10_write(dcss, ch_num, *map, ctrl_ofs); +} + +static int dcss_hdr10_ch_init_all(struct dcss_soc *dcss, + unsigned long hdr10_base) +{ + struct dcss_hdr10_priv *hdr10 = dcss->hdr10_priv; + struct dcss_hdr10_ch *ch; + int i; + + for (i = 0; i < 4; i++) { + ch = &hdr10->ch[i]; + + ch->base_ofs = hdr10_base + i * 0x4000; + + ch->base_reg = devm_ioremap(dcss->dev, ch->base_ofs, SZ_16K); + if (!ch->base_reg) { + dev_err(dcss->dev, "hdr10: unable to remap ch base\n"); + return -ENOMEM; + } + + ch->old_cfg_desc = HDR10_DESC_INVALID; + +#if defined(USE_CTXLD) + ch->ctx_id = CTX_SB_HP; +#endif + } + + return 0; +} + +static u32 *dcss_hdr10_find_tbl(u64 desc, struct list_head *head) +{ + struct list_head *node; + struct dcss_hdr10_tbl_node *tbl_node; + + list_for_each(node, head) { + tbl_node = container_of(node, struct dcss_hdr10_tbl_node, node); + + if ((tbl_node->tbl_descriptor & desc) == desc) + return tbl_node->tbl_data; + } + + return NULL; +} + +static int dcss_hdr10_get_tbls(struct dcss_hdr10_priv *hdr10, bool input, + u64 desc, u32 **lut, u32 **csca, u32 **cscb) +{ + struct list_head *lut_list, *csca_list, *cscb_list; + + lut_list = input ? &hdr10->ipipe_tbls->lut : &hdr10->opipe_tbls->lut; + csca_list = input ? &hdr10->ipipe_tbls->csca : &hdr10->opipe_tbls->csc; + cscb_list = input ? &hdr10->ipipe_tbls->cscb : NULL; + + *lut = dcss_hdr10_find_tbl(desc, lut_list); + *csca = dcss_hdr10_find_tbl(desc, csca_list); + + *cscb = NULL; + if (cscb_list) + *cscb = dcss_hdr10_find_tbl(desc, cscb_list); + + return 0; +} + +static void dcss_hdr10_write_pipe_tbls(struct dcss_soc *dcss, int ch_num, + u32 *lut, u32 *csca, u32 *cscb) +{ + if (csca) + dcss_hdr10_csc_fill(dcss, ch_num, HDR10_CSCA, csca); + + if (ch_num != OPIPE_CH_NO && cscb) + dcss_hdr10_csc_fill(dcss, ch_num, HDR10_CSCB, cscb); + + if (lut) + dcss_hdr10_lut_fill(dcss, ch_num, lut); +} + +static void dcss_hdr10_tbl_add(struct dcss_hdr10_priv *hdr10, u64 desc, u32 sz, + u32 *data) +{ + struct device *dev = hdr10->dcss->dev; + struct dcss_hdr10_tbl_node *node; + + node = devm_kzalloc(dev, sizeof(*node), GFP_KERNEL); + if (!node) { + dev_err(dev, "hdr10: cannot alloc memory for table node.\n"); + return; + } + + /* we don't need to store the table type and pipe type */ + node->tbl_descriptor = desc >> 4; + node->tbl_data = data; + + if (!(desc & HDR10_PT_OUTPUT)) { + if (desc & HDR10_TT_LUT) + list_add(&node->node, &hdr10->ipipe_tbls->lut); + else if (desc & HDR10_TT_CSCA) + list_add(&node->node, &hdr10->ipipe_tbls->csca); + else if (desc & HDR10_TT_CSCB) + list_add(&node->node, &hdr10->ipipe_tbls->cscb); + + return; + } + + if (desc & HDR10_TT_LUT) + list_add(&node->node, &hdr10->opipe_tbls->lut); + else if (desc & HDR10_TT_CSCA) + list_add(&node->node, &hdr10->opipe_tbls->csc); +} + +static void dcss_hdr10_parse_fw_data(struct dcss_hdr10_priv *hdr10) +{ + u32 *data = (u32 *)hdr10->fw_data; + u32 remaining = hdr10->fw_size / sizeof(u32); + u64 tbl_desc; + u32 tbl_size; + + while (remaining) { + tbl_desc = *((u64 *)data); + data += 2; + tbl_size = *data++; + + dcss_hdr10_tbl_add(hdr10, tbl_desc, tbl_size, data); + + data += tbl_size; + remaining -= tbl_size + 3; + } +} + +#ifndef USE_TBL_HEADER +static void dcss_hdr10_fw_handler(const struct firmware *fw, void *context) +{ + struct dcss_hdr10_priv *hdr10 = context; + int i; + + if (!fw) { + dev_err(hdr10->dcss->dev, "hdr10: DCSS FW load failed.\n"); + return; + } + + /* we need to keep the tables for the entire life of the driver */ + hdr10->fw_data = devm_kzalloc(hdr10->dcss->dev, fw->size, GFP_KERNEL); + if (!hdr10->fw_data) { + dev_err(hdr10->dcss->dev, "hdr10: cannot alloc FW memory.\n"); + return; + } + + memcpy(hdr10->fw_data, fw->data, fw->size); + hdr10->fw_size = fw->size; + + release_firmware(fw); + + dcss_hdr10_parse_fw_data(hdr10); + + for (i = 0; i < 4; i++) { + u32 *lut, *csca, *cscb; + struct dcss_hdr10_ch *ch = &hdr10->ch[i]; + bool is_input_pipe = i != OPIPE_CH_NO ? true : false; + + if (ch->old_cfg_desc != HDR10_DESC_INVALID) { + dcss_hdr10_get_tbls(hdr10, is_input_pipe, + ch->old_cfg_desc, &lut, + &csca, &cscb); + dcss_hdr10_write_pipe_tbls(hdr10->dcss, i, lut, + csca, cscb); + } + } + + dev_info(hdr10->dcss->dev, "hdr10: DCSS FW loaded successfully\n"); +} +#endif + +static int dcss_hdr10_tbls_init(struct dcss_hdr10_priv *hdr10) +{ + struct device *dev = hdr10->dcss->dev; + + hdr10->ipipe_tbls = devm_kzalloc(dev, sizeof(*hdr10->ipipe_tbls), + GFP_KERNEL); + if (!hdr10->ipipe_tbls) + return -ENOMEM; + + INIT_LIST_HEAD(&hdr10->ipipe_tbls->lut); + INIT_LIST_HEAD(&hdr10->ipipe_tbls->csca); + INIT_LIST_HEAD(&hdr10->ipipe_tbls->cscb); + + hdr10->opipe_tbls = devm_kzalloc(dev, sizeof(*hdr10->opipe_tbls), + GFP_KERNEL); + if (!hdr10->opipe_tbls) + return -ENOMEM; + + INIT_LIST_HEAD(&hdr10->opipe_tbls->lut); + INIT_LIST_HEAD(&hdr10->opipe_tbls->csc); + + return 0; +} + +int dcss_hdr10_init(struct dcss_soc *dcss, unsigned long hdr10_base) +{ + int ret; + struct dcss_hdr10_priv *hdr10; + + hdr10 = devm_kzalloc(dcss->dev, sizeof(*hdr10), GFP_KERNEL); + if (!hdr10) + return -ENOMEM; + + dcss->hdr10_priv = hdr10; + hdr10->dcss = dcss; + + ret = dcss_hdr10_tbls_init(hdr10); + if (ret < 0) { + dev_err(dcss->dev, "hdr10: Cannot init table lists.\n"); + return ret; + } + +#ifndef USE_TBL_HEADER + ret = request_firmware_nowait(THIS_MODULE, FW_ACTION_HOTPLUG, "dcss.fw", + dcss->dev, GFP_KERNEL, hdr10, + dcss_hdr10_fw_handler); + if (ret < 0) { + dev_err(dcss->dev, "hdr10: Cannot async load DCSS FW.\n"); + return ret; + } +#else + hdr10->fw_data = (u8 *)dcss_hdr10_tables; + hdr10->fw_size = sizeof(dcss_hdr10_tables); + + dcss_hdr10_parse_fw_data(hdr10); +#endif + + return dcss_hdr10_ch_init_all(dcss, hdr10_base); +} + +void dcss_hdr10_exit(struct dcss_soc *dcss) +{ +} + +static u32 dcss_hdr10_get_bpc(u32 pix_format) +{ + int bpp; + u32 depth, bpc; + + switch (pix_format) { + case DRM_FORMAT_NV12: + case DRM_FORMAT_NV21: + bpc = 8; + break; + + case DRM_FORMAT_UYVY: + case DRM_FORMAT_VYUY: + case DRM_FORMAT_YUYV: + case DRM_FORMAT_YVYU: + bpc = 8; + break; + + case DRM_FORMAT_P010: + bpc = 10; + break; + + default: + drm_fb_get_bpp_depth(pix_format, &depth, &bpp); + bpc = depth == 30 ? 10 : 8; + break; + } + + return bpc; +} + +static u32 dcss_hdr10_pipe_desc(struct dcss_hdr10_pipe_cfg *pipe_cfg) +{ + u32 bpc, cs, desc; + + bpc = dcss_hdr10_get_bpc(pipe_cfg->pixel_format); + cs = dcss_drm_fourcc_to_colorspace(pipe_cfg->pixel_format); + + desc = bpc == 10 ? 2 << HDR10_BPC_POS : 1 << HDR10_BPC_POS; + desc |= cs == DCSS_COLORSPACE_YUV ? 2 << HDR10_CS_POS : + 1 << HDR10_CS_POS; + desc |= ((1 << pipe_cfg->nl) << HDR10_NL_POS) & HDR10_NL_MASK; + desc |= ((1 << pipe_cfg->pr) << HDR10_PR_POS) & HDR10_PR_MASK; + desc |= ((1 << pipe_cfg->g) << HDR10_G_POS) & HDR10_G_MASK; + + return desc; +} + +static u64 dcss_hdr10_get_desc(struct dcss_hdr10_pipe_cfg *ipipe_cfg, + struct dcss_hdr10_pipe_cfg *opipe_cfg) +{ + u32 ipipe_desc, opipe_desc; + + ipipe_desc = dcss_hdr10_pipe_desc(ipipe_cfg) & (~HDR10_BPC_MASK); + ipipe_desc |= 2 << HDR10_BPC_POS; + opipe_desc = dcss_hdr10_pipe_desc(opipe_cfg); + + return (ipipe_desc & 0xFFFF) | + (opipe_desc & 0xFFFF) << 16; +} + +static void dcss_hdr10_pipe_setup(struct dcss_soc *dcss, int ch_num, + u64 desc) +{ + struct dcss_hdr10_ch *ch = &dcss->hdr10_priv->ch[ch_num]; + bool pipe_cfg_chgd; + u32 *csca, *cscb, *lut; + + pipe_cfg_chgd = ch->old_cfg_desc != desc; + + if (!pipe_cfg_chgd) + return; + + dcss_hdr10_get_tbls(dcss->hdr10_priv, ch_num != OPIPE_CH_NO, + desc, &lut, &csca, &cscb); + dcss_hdr10_write_pipe_tbls(dcss, ch_num, lut, csca, cscb); + + ch->old_cfg_desc = desc; +} + +void dcss_hdr10_setup(struct dcss_soc *dcss, int ch_num, + struct dcss_hdr10_pipe_cfg *ipipe_cfg, + struct dcss_hdr10_pipe_cfg *opipe_cfg) +{ + u64 desc = dcss_hdr10_get_desc(ipipe_cfg, opipe_cfg); + + dcss_hdr10_pipe_setup(dcss, ch_num, desc); + + /* + * Input pipe configuration doesn't matter for configuring the output + * pipe. So, will just mask off the input part of the descriptor. + */ + dcss_hdr10_pipe_setup(dcss, OPIPE_CH_NO, desc | 0xfffe); +} +EXPORT_SYMBOL(dcss_hdr10_setup); |