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

media: qcom: camss: Add support for MSM8939

The camera subsystem for the MSM8939 is the same as MSM8916 except with
3 CSID instead of 2, and some higher clock rates.

As a quirk, this SoC needs writing values to 2 VFE VBIF registers
(see downstream msm8939-camera.dtsi vbif-{regs,settings} properties).
This fixes black stripes across sensor and garbage in CSID TPG outputs.

Add support for the MSM8939 camera subsystem.

Reviewed-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org>
Signed-off-by: Vincent Knecht <vincent.knecht@mailoo.org>
Signed-off-by: André Apitzsch <git@apitzsch.eu>
Signed-off-by: Bryan O'Donoghue <bod@kernel.org>
Signed-off-by: Hans Verkuil <hverkuil+cisco@kernel.org>

authored by

Vincent Knecht and committed by
Hans Verkuil
b4fbb13d f0e8ffb4

+171 -2
+1
drivers/media/platform/qcom/camss/camss-csiphy.c
··· 600 600 return PTR_ERR(csiphy->base); 601 601 602 602 if (camss->res->version == CAMSS_8x16 || 603 + camss->res->version == CAMSS_8x39 || 603 604 camss->res->version == CAMSS_8x53 || 604 605 camss->res->version == CAMSS_8x96) { 605 606 csiphy->base_clk_mux =
+6 -2
drivers/media/platform/qcom/camss/camss-ispif.c
··· 1112 1112 /* Number of ISPIF lines - same as number of CSID hardware modules */ 1113 1113 if (camss->res->version == CAMSS_8x16) 1114 1114 ispif->line_num = 2; 1115 + else if (camss->res->version == CAMSS_8x39) 1116 + ispif->line_num = 3; 1115 1117 else if (camss->res->version == CAMSS_8x96 || 1116 1118 camss->res->version == CAMSS_8x53 || 1117 1119 camss->res->version == CAMSS_660) ··· 1130 1128 ispif->line[i].ispif = ispif; 1131 1129 ispif->line[i].id = i; 1132 1130 1133 - if (camss->res->version == CAMSS_8x16) { 1131 + if (camss->res->version == CAMSS_8x16 || 1132 + camss->res->version == CAMSS_8x39) { 1134 1133 ispif->line[i].formats = ispif_formats_8x16; 1135 1134 ispif->line[i].nformats = 1136 1135 ARRAY_SIZE(ispif_formats_8x16); ··· 1165 1162 ispif->irq = ret; 1166 1163 snprintf(ispif->irq_name, sizeof(ispif->irq_name), "%s_%s", 1167 1164 dev_name(dev), MSM_ISPIF_NAME); 1168 - if (camss->res->version == CAMSS_8x16) 1165 + if (camss->res->version == CAMSS_8x16 || 1166 + camss->res->version == CAMSS_8x39) 1169 1167 ret = devm_request_irq(dev, ispif->irq, ispif_isr_8x16, 1170 1168 IRQF_TRIGGER_RISING, ispif->irq_name, ispif); 1171 1169 else if (camss->res->version == CAMSS_8x96 ||
+6
drivers/media/platform/qcom/camss/camss-vfe-vbif.c
··· 14 14 #include "camss-vfe.h" 15 15 #include "camss-vfe-vbif.h" 16 16 17 + #define VBIF_FIXED_SORT_EN 0x30 18 + #define VBIF_FIXED_SORT_SEL0 0x34 19 + 17 20 void vfe_vbif_write_reg(struct vfe_device *vfe, u32 reg, u32 val) 18 21 { 19 22 writel_relaxed(val, vfe->vbif_base + reg); ··· 24 21 25 22 int vfe_vbif_apply_settings(struct vfe_device *vfe) 26 23 { 24 + vfe_vbif_write_reg(vfe, VBIF_FIXED_SORT_EN, 0xfff); 25 + vfe_vbif_write_reg(vfe, VBIF_FIXED_SORT_SEL0, 0x555000); 26 + 27 27 return 0; 28 28 }
+1
drivers/media/platform/qcom/camss/camss-vfe.c
··· 290 290 291 291 switch (vfe->camss->res->version) { 292 292 case CAMSS_8x16: 293 + case CAMSS_8x39: 293 294 case CAMSS_8x53: 294 295 switch (sink_code) { 295 296 case MEDIA_BUS_FMT_YUYV8_1X16:
+156
drivers/media/platform/qcom/camss/camss.c
··· 154 154 } 155 155 }; 156 156 157 + static const struct camss_subdev_resources csiphy_res_8x39[] = { 158 + /* CSIPHY0 */ 159 + { 160 + .regulators = { "vdda" }, 161 + .clock = { "top_ahb", "ispif_ahb", "ahb", "csiphy0_timer" }, 162 + .clock_rate = { { 0 }, 163 + { 40000000, 80000000 }, 164 + { 0 }, 165 + { 100000000, 200000000 } }, 166 + .reg = { "csiphy0", "csiphy0_clk_mux" }, 167 + .interrupt = { "csiphy0" }, 168 + .csiphy = { 169 + .id = 0, 170 + .hw_ops = &csiphy_ops_2ph_1_0, 171 + .formats = &csiphy_formats_8x16 172 + } 173 + }, 174 + 175 + /* CSIPHY1 */ 176 + { 177 + .regulators = { "vdda" }, 178 + .clock = { "top_ahb", "ispif_ahb", "ahb", "csiphy1_timer" }, 179 + .clock_rate = { { 0 }, 180 + { 40000000, 80000000 }, 181 + { 0 }, 182 + { 100000000, 200000000 } }, 183 + .reg = { "csiphy1", "csiphy1_clk_mux" }, 184 + .interrupt = { "csiphy1" }, 185 + .csiphy = { 186 + .id = 1, 187 + .hw_ops = &csiphy_ops_2ph_1_0, 188 + .formats = &csiphy_formats_8x16 189 + } 190 + } 191 + }; 192 + 193 + static const struct camss_subdev_resources csid_res_8x39[] = { 194 + /* CSID0 */ 195 + { 196 + .regulators = {}, 197 + .clock = { "top_ahb", "ispif_ahb", "csi0_ahb", "ahb", 198 + "csi0", "csi0_phy", "csi0_pix", "csi0_rdi" }, 199 + .clock_rate = { { 0 }, 200 + { 40000000, 80000000 }, 201 + { 0 }, 202 + { 0 }, 203 + { 100000000, 200000000 }, 204 + { 0 }, 205 + { 0 }, 206 + { 0 } }, 207 + .reg = { "csid0" }, 208 + .interrupt = { "csid0" }, 209 + .csid = { 210 + .hw_ops = &csid_ops_4_1, 211 + .parent_dev_ops = &vfe_parent_dev_ops, 212 + .formats = &csid_formats_4_1 213 + } 214 + }, 215 + 216 + /* CSID1 */ 217 + { 218 + .regulators = {}, 219 + .clock = { "top_ahb", "ispif_ahb", "csi1_ahb", "ahb", 220 + "csi1", "csi1_phy", "csi1_pix", "csi1_rdi" }, 221 + .clock_rate = { { 0 }, 222 + { 40000000, 80000000 }, 223 + { 0 }, 224 + { 0 }, 225 + { 100000000, 200000000 }, 226 + { 0 }, 227 + { 0 }, 228 + { 0 } }, 229 + .reg = { "csid1" }, 230 + .interrupt = { "csid1" }, 231 + .csid = { 232 + .hw_ops = &csid_ops_4_1, 233 + .parent_dev_ops = &vfe_parent_dev_ops, 234 + .formats = &csid_formats_4_1 235 + } 236 + }, 237 + 238 + /* CSID2 */ 239 + { 240 + .regulators = {}, 241 + .clock = { "top_ahb", "ispif_ahb", "csi2_ahb", "ahb", 242 + "csi2", "csi2_phy", "csi2_pix", "csi2_rdi" }, 243 + .clock_rate = { { 0 }, 244 + { 40000000, 80000000 }, 245 + { 0 }, 246 + { 0 }, 247 + { 100000000, 200000000 }, 248 + { 0 }, 249 + { 0 }, 250 + { 0 } }, 251 + .reg = { "csid2" }, 252 + .interrupt = { "csid2" }, 253 + .csid = { 254 + .hw_ops = &csid_ops_4_1, 255 + .parent_dev_ops = &vfe_parent_dev_ops, 256 + .formats = &csid_formats_4_1 257 + } 258 + }, 259 + }; 260 + 261 + static const struct camss_subdev_resources ispif_res_8x39 = { 262 + /* ISPIF */ 263 + .clock = { "top_ahb", "ispif_ahb", "ahb", 264 + "csi0", "csi0_pix", "csi0_rdi", 265 + "csi1", "csi1_pix", "csi1_rdi", 266 + "csi2", "csi2_pix", "csi2_rdi" }, 267 + .clock_for_reset = { "vfe0", "csi_vfe0" }, 268 + .reg = { "ispif", "csi_clk_mux" }, 269 + .interrupt = { "ispif" }, 270 + }; 271 + 272 + static const struct camss_subdev_resources vfe_res_8x39[] = { 273 + /* VFE0 */ 274 + { 275 + .regulators = {}, 276 + .clock = { "top_ahb", "ispif_ahb", "vfe0", "csi_vfe0", 277 + "vfe_ahb", "vfe_axi", "ahb" }, 278 + .clock_rate = { { 0 }, 279 + { 40000000, 80000000 }, 280 + { 50000000, 80000000, 100000000, 160000000, 281 + 177780000, 200000000, 266670000, 320000000, 282 + 400000000, 465000000, 480000000, 600000000 }, 283 + { 0 }, 284 + { 0 }, 285 + { 0 }, 286 + { 0 } }, 287 + .reg = { "vfe0" }, 288 + .interrupt = { "vfe0" }, 289 + .vfe = { 290 + .line_num = 3, 291 + .has_vbif = true, 292 + .vbif_name = "vfe0_vbif", 293 + .hw_ops = &vfe_ops_4_1, 294 + .formats_rdi = &vfe_formats_rdi_8x16, 295 + .formats_pix = &vfe_formats_pix_8x16 296 + } 297 + } 298 + }; 299 + 157 300 static const struct camss_subdev_resources csid_res_8x53[] = { 158 301 /* CSID0 */ 159 302 { ··· 4625 4482 return -ENOMEM; 4626 4483 4627 4484 if (camss->res->version == CAMSS_8x16 || 4485 + camss->res->version == CAMSS_8x39 || 4628 4486 camss->res->version == CAMSS_8x53 || 4629 4487 camss->res->version == CAMSS_8x96) { 4630 4488 camss->ispif = devm_kcalloc(dev, 1, sizeof(*camss->ispif), GFP_KERNEL); ··· 4755 4611 .csiphy_num = ARRAY_SIZE(csiphy_res_8x16), 4756 4612 .csid_num = ARRAY_SIZE(csid_res_8x16), 4757 4613 .vfe_num = ARRAY_SIZE(vfe_res_8x16), 4614 + }; 4615 + 4616 + static const struct camss_resources msm8939_resources = { 4617 + .version = CAMSS_8x39, 4618 + .csiphy_res = csiphy_res_8x39, 4619 + .csid_res = csid_res_8x39, 4620 + .ispif_res = &ispif_res_8x39, 4621 + .vfe_res = vfe_res_8x39, 4622 + .csiphy_num = ARRAY_SIZE(csiphy_res_8x39), 4623 + .csid_num = ARRAY_SIZE(csid_res_8x39), 4624 + .vfe_num = ARRAY_SIZE(vfe_res_8x39), 4758 4625 }; 4759 4626 4760 4627 static const struct camss_resources msm8953_resources = { ··· 4948 4793 4949 4794 static const struct of_device_id camss_dt_match[] = { 4950 4795 { .compatible = "qcom,msm8916-camss", .data = &msm8916_resources }, 4796 + { .compatible = "qcom,msm8939-camss", .data = &msm8939_resources }, 4951 4797 { .compatible = "qcom,msm8953-camss", .data = &msm8953_resources }, 4952 4798 { .compatible = "qcom,msm8996-camss", .data = &msm8996_resources }, 4953 4799 { .compatible = "qcom,qcm2290-camss", .data = &qcm2290_resources },
+1
drivers/media/platform/qcom/camss/camss.h
··· 82 82 CAMSS_2290, 83 83 CAMSS_7280, 84 84 CAMSS_8x16, 85 + CAMSS_8x39, 85 86 CAMSS_8x53, 86 87 CAMSS_8x96, 87 88 CAMSS_8250,