Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v6.19-rc5 222 lines 6.1 kB view raw
1// SPDX-License-Identifier: GPL-2.0+ 2/* 3 * Copyright 2024 NXP 4 */ 5 6#include <linux/component.h> 7#include <linux/mod_devicetable.h> 8#include <linux/module.h> 9#include <linux/platform_device.h> 10#include <linux/regmap.h> 11 12#include <drm/drm_fourcc.h> 13 14#include "dc-drv.h" 15#include "dc-fu.h" 16 17#define PIXENGCFG_DYNAMIC 0x8 18 19#define BASEADDRESS(x) (0x10 + FRAC_OFFSET * (x)) 20#define SOURCEBUFFERATTRIBUTES(x) (0x14 + FRAC_OFFSET * (x)) 21#define SOURCEBUFFERDIMENSION(x) (0x18 + FRAC_OFFSET * (x)) 22#define COLORCOMPONENTBITS(x) (0x1c + FRAC_OFFSET * (x)) 23#define COLORCOMPONENTSHIFT(x) (0x20 + FRAC_OFFSET * (x)) 24#define LAYEROFFSET(x) (0x24 + FRAC_OFFSET * (x)) 25#define CLIPWINDOWOFFSET(x) (0x28 + FRAC_OFFSET * (x)) 26#define CLIPWINDOWDIMENSIONS(x) (0x2c + FRAC_OFFSET * (x)) 27#define CONSTANTCOLOR(x) (0x30 + FRAC_OFFSET * (x)) 28#define LAYERPROPERTY(x) (0x34 + FRAC_OFFSET * (x)) 29#define FRAMEDIMENSIONS 0x150 30#define CONTROL 0x170 31 32struct dc_fw { 33 struct dc_fu fu; 34}; 35 36static const struct dc_subdev_info dc_fw_info[] = { 37 { .reg_start = 0x56180a60, .id = 2, }, 38}; 39 40static const struct regmap_range dc_fw_pec_regmap_access_ranges[] = { 41 regmap_reg_range(PIXENGCFG_DYNAMIC, PIXENGCFG_DYNAMIC), 42}; 43 44static const struct regmap_access_table dc_fw_pec_regmap_access_table = { 45 .yes_ranges = dc_fw_pec_regmap_access_ranges, 46 .n_yes_ranges = ARRAY_SIZE(dc_fw_pec_regmap_access_ranges), 47}; 48 49static const struct regmap_config dc_fw_pec_regmap_config = { 50 .name = "pec", 51 .reg_bits = 32, 52 .reg_stride = 4, 53 .val_bits = 32, 54 .fast_io = true, 55 .wr_table = &dc_fw_pec_regmap_access_table, 56 .rd_table = &dc_fw_pec_regmap_access_table, 57 .max_register = PIXENGCFG_DYNAMIC, 58}; 59 60static const struct regmap_range dc_fw_regmap_ranges[] = { 61 regmap_reg_range(STATICCONTROL, FRAMEDIMENSIONS), 62 regmap_reg_range(CONTROL, CONTROL), 63}; 64 65static const struct regmap_access_table dc_fw_regmap_access_table = { 66 .yes_ranges = dc_fw_regmap_ranges, 67 .n_yes_ranges = ARRAY_SIZE(dc_fw_regmap_ranges), 68}; 69 70static const struct regmap_config dc_fw_cfg_regmap_config = { 71 .name = "cfg", 72 .reg_bits = 32, 73 .reg_stride = 4, 74 .val_bits = 32, 75 .fast_io = true, 76 .wr_table = &dc_fw_regmap_access_table, 77 .rd_table = &dc_fw_regmap_access_table, 78 .max_register = CONTROL, 79}; 80 81static void dc_fw_set_fmt(struct dc_fu *fu, enum dc_fu_frac frac, 82 const struct drm_format_info *format) 83{ 84 u32 bits = 0, shifts = 0; 85 86 dc_fu_set_src_bpp(fu, frac, format->cpp[0] * 8); 87 88 regmap_write_bits(fu->reg_cfg, CONTROL, INPUTSELECT_MASK, 89 INPUTSELECT(INPUTSELECT_INACTIVE)); 90 regmap_write_bits(fu->reg_cfg, CONTROL, RASTERMODE_MASK, 91 RASTERMODE(RASTERMODE_NORMAL)); 92 93 regmap_write_bits(fu->reg_cfg, LAYERPROPERTY(frac), 94 YUVCONVERSIONMODE_MASK, 95 YUVCONVERSIONMODE(YUVCONVERSIONMODE_OFF)); 96 97 dc_fu_get_pixel_format_bits(fu, format->format, &bits); 98 dc_fu_get_pixel_format_shifts(fu, format->format, &shifts); 99 100 regmap_write(fu->reg_cfg, COLORCOMPONENTBITS(frac), bits); 101 regmap_write(fu->reg_cfg, COLORCOMPONENTSHIFT(frac), shifts); 102} 103 104static void dc_fw_set_framedimensions(struct dc_fu *fu, int w, int h) 105{ 106 regmap_write(fu->reg_cfg, FRAMEDIMENSIONS, 107 FRAMEWIDTH(w) | FRAMEHEIGHT(h)); 108} 109 110static void dc_fw_init(struct dc_fu *fu) 111{ 112 regmap_write(fu->reg_pec, PIXENGCFG_DYNAMIC, LINK_ID_NONE); 113 dc_fu_common_hw_init(fu); 114 dc_fu_shdldreq_sticky(fu, 0xff); 115} 116 117static void dc_fw_set_ops(struct dc_fu *fu) 118{ 119 memcpy(&fu->ops, &dc_fu_common_ops, sizeof(dc_fu_common_ops)); 120 fu->ops.init = dc_fw_init; 121 fu->ops.set_fmt = dc_fw_set_fmt; 122 fu->ops.set_framedimensions = dc_fw_set_framedimensions; 123} 124 125static int dc_fw_bind(struct device *dev, struct device *master, void *data) 126{ 127 struct platform_device *pdev = to_platform_device(dev); 128 struct dc_drm_device *dc_drm = data; 129 struct resource *res_pec; 130 void __iomem *base_pec; 131 void __iomem *base_cfg; 132 struct dc_fw *fw; 133 struct dc_fu *fu; 134 int i, id; 135 136 fw = devm_kzalloc(dev, sizeof(*fw), GFP_KERNEL); 137 if (!fw) 138 return -ENOMEM; 139 140 fu = &fw->fu; 141 142 base_pec = devm_platform_get_and_ioremap_resource(pdev, 0, &res_pec); 143 if (IS_ERR(base_pec)) 144 return PTR_ERR(base_pec); 145 146 base_cfg = devm_platform_ioremap_resource_byname(pdev, "cfg"); 147 if (IS_ERR(base_cfg)) 148 return PTR_ERR(base_cfg); 149 150 fu->reg_pec = devm_regmap_init_mmio(dev, base_pec, 151 &dc_fw_pec_regmap_config); 152 if (IS_ERR(fu->reg_pec)) 153 return PTR_ERR(fu->reg_pec); 154 155 fu->reg_cfg = devm_regmap_init_mmio(dev, base_cfg, 156 &dc_fw_cfg_regmap_config); 157 if (IS_ERR(fu->reg_cfg)) 158 return PTR_ERR(fu->reg_cfg); 159 160 id = dc_subdev_get_id(dc_fw_info, ARRAY_SIZE(dc_fw_info), res_pec); 161 if (id < 0) { 162 dev_err(dev, "failed to get instance number: %d\n", id); 163 return id; 164 } 165 166 fu->link_id = LINK_ID_FETCHWARP2; 167 fu->id = DC_FETCHUNIT_FW2; 168 for (i = 0; i < DC_FETCHUNIT_FRAC_NUM; i++) { 169 fu->reg_baseaddr[i] = BASEADDRESS(i); 170 fu->reg_sourcebufferattributes[i] = SOURCEBUFFERATTRIBUTES(i); 171 fu->reg_sourcebufferdimension[i] = SOURCEBUFFERDIMENSION(i); 172 fu->reg_layeroffset[i] = LAYEROFFSET(i); 173 fu->reg_clipwindowoffset[i] = CLIPWINDOWOFFSET(i); 174 fu->reg_clipwindowdimensions[i] = CLIPWINDOWDIMENSIONS(i); 175 fu->reg_constantcolor[i] = CONSTANTCOLOR(i); 176 fu->reg_layerproperty[i] = LAYERPROPERTY(i); 177 } 178 snprintf(fu->name, sizeof(fu->name), "FetchWarp%d", id); 179 180 dc_fw_set_ops(fu); 181 182 dc_drm->fu_disp[fu->id] = fu; 183 184 return 0; 185} 186 187static const struct component_ops dc_fw_ops = { 188 .bind = dc_fw_bind, 189}; 190 191static int dc_fw_probe(struct platform_device *pdev) 192{ 193 int ret; 194 195 ret = component_add(&pdev->dev, &dc_fw_ops); 196 if (ret) 197 return dev_err_probe(&pdev->dev, ret, 198 "failed to add component\n"); 199 200 return 0; 201} 202 203static void dc_fw_remove(struct platform_device *pdev) 204{ 205 component_del(&pdev->dev, &dc_fw_ops); 206} 207 208static const struct of_device_id dc_fw_dt_ids[] = { 209 { .compatible = "fsl,imx8qxp-dc-fetchwarp" }, 210 { /* sentinel */ } 211}; 212MODULE_DEVICE_TABLE(of, dc_fw_dt_ids); 213 214struct platform_driver dc_fw_driver = { 215 .probe = dc_fw_probe, 216 .remove = dc_fw_remove, 217 .driver = { 218 .name = "imx8-dc-fetchwarp", 219 .suppress_bind_attrs = true, 220 .of_match_table = dc_fw_dt_ids, 221 }, 222};