mirror of
https://github.com/torvalds/linux.git
synced 2026-05-28 09:04:39 +02:00
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>
This commit is contained in:
parent
f0e8ffb46b
commit
b4fbb13db8
|
|
@ -600,6 +600,7 @@ int msm_csiphy_subdev_init(struct camss *camss,
|
|||
return PTR_ERR(csiphy->base);
|
||||
|
||||
if (camss->res->version == CAMSS_8x16 ||
|
||||
camss->res->version == CAMSS_8x39 ||
|
||||
camss->res->version == CAMSS_8x53 ||
|
||||
camss->res->version == CAMSS_8x96) {
|
||||
csiphy->base_clk_mux =
|
||||
|
|
|
|||
|
|
@ -1112,6 +1112,8 @@ int msm_ispif_subdev_init(struct camss *camss,
|
|||
/* Number of ISPIF lines - same as number of CSID hardware modules */
|
||||
if (camss->res->version == CAMSS_8x16)
|
||||
ispif->line_num = 2;
|
||||
else if (camss->res->version == CAMSS_8x39)
|
||||
ispif->line_num = 3;
|
||||
else if (camss->res->version == CAMSS_8x96 ||
|
||||
camss->res->version == CAMSS_8x53 ||
|
||||
camss->res->version == CAMSS_660)
|
||||
|
|
@ -1128,7 +1130,8 @@ int msm_ispif_subdev_init(struct camss *camss,
|
|||
ispif->line[i].ispif = ispif;
|
||||
ispif->line[i].id = i;
|
||||
|
||||
if (camss->res->version == CAMSS_8x16) {
|
||||
if (camss->res->version == CAMSS_8x16 ||
|
||||
camss->res->version == CAMSS_8x39) {
|
||||
ispif->line[i].formats = ispif_formats_8x16;
|
||||
ispif->line[i].nformats =
|
||||
ARRAY_SIZE(ispif_formats_8x16);
|
||||
|
|
@ -1162,7 +1165,8 @@ int msm_ispif_subdev_init(struct camss *camss,
|
|||
ispif->irq = ret;
|
||||
snprintf(ispif->irq_name, sizeof(ispif->irq_name), "%s_%s",
|
||||
dev_name(dev), MSM_ISPIF_NAME);
|
||||
if (camss->res->version == CAMSS_8x16)
|
||||
if (camss->res->version == CAMSS_8x16 ||
|
||||
camss->res->version == CAMSS_8x39)
|
||||
ret = devm_request_irq(dev, ispif->irq, ispif_isr_8x16,
|
||||
IRQF_TRIGGER_RISING, ispif->irq_name, ispif);
|
||||
else if (camss->res->version == CAMSS_8x96 ||
|
||||
|
|
|
|||
|
|
@ -14,6 +14,9 @@
|
|||
#include "camss-vfe.h"
|
||||
#include "camss-vfe-vbif.h"
|
||||
|
||||
#define VBIF_FIXED_SORT_EN 0x30
|
||||
#define VBIF_FIXED_SORT_SEL0 0x34
|
||||
|
||||
void vfe_vbif_write_reg(struct vfe_device *vfe, u32 reg, u32 val)
|
||||
{
|
||||
writel_relaxed(val, vfe->vbif_base + reg);
|
||||
|
|
@ -21,5 +24,8 @@ void vfe_vbif_write_reg(struct vfe_device *vfe, u32 reg, u32 val)
|
|||
|
||||
int vfe_vbif_apply_settings(struct vfe_device *vfe)
|
||||
{
|
||||
vfe_vbif_write_reg(vfe, VBIF_FIXED_SORT_EN, 0xfff);
|
||||
vfe_vbif_write_reg(vfe, VBIF_FIXED_SORT_SEL0, 0x555000);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -290,6 +290,7 @@ static u32 vfe_src_pad_code(struct vfe_line *line, u32 sink_code,
|
|||
|
||||
switch (vfe->camss->res->version) {
|
||||
case CAMSS_8x16:
|
||||
case CAMSS_8x39:
|
||||
case CAMSS_8x53:
|
||||
switch (sink_code) {
|
||||
case MEDIA_BUS_FMT_YUYV8_1X16:
|
||||
|
|
|
|||
|
|
@ -154,6 +154,149 @@ static const struct camss_subdev_resources vfe_res_8x16[] = {
|
|||
}
|
||||
};
|
||||
|
||||
static const struct camss_subdev_resources csiphy_res_8x39[] = {
|
||||
/* CSIPHY0 */
|
||||
{
|
||||
.regulators = { "vdda" },
|
||||
.clock = { "top_ahb", "ispif_ahb", "ahb", "csiphy0_timer" },
|
||||
.clock_rate = { { 0 },
|
||||
{ 40000000, 80000000 },
|
||||
{ 0 },
|
||||
{ 100000000, 200000000 } },
|
||||
.reg = { "csiphy0", "csiphy0_clk_mux" },
|
||||
.interrupt = { "csiphy0" },
|
||||
.csiphy = {
|
||||
.id = 0,
|
||||
.hw_ops = &csiphy_ops_2ph_1_0,
|
||||
.formats = &csiphy_formats_8x16
|
||||
}
|
||||
},
|
||||
|
||||
/* CSIPHY1 */
|
||||
{
|
||||
.regulators = { "vdda" },
|
||||
.clock = { "top_ahb", "ispif_ahb", "ahb", "csiphy1_timer" },
|
||||
.clock_rate = { { 0 },
|
||||
{ 40000000, 80000000 },
|
||||
{ 0 },
|
||||
{ 100000000, 200000000 } },
|
||||
.reg = { "csiphy1", "csiphy1_clk_mux" },
|
||||
.interrupt = { "csiphy1" },
|
||||
.csiphy = {
|
||||
.id = 1,
|
||||
.hw_ops = &csiphy_ops_2ph_1_0,
|
||||
.formats = &csiphy_formats_8x16
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
static const struct camss_subdev_resources csid_res_8x39[] = {
|
||||
/* CSID0 */
|
||||
{
|
||||
.regulators = {},
|
||||
.clock = { "top_ahb", "ispif_ahb", "csi0_ahb", "ahb",
|
||||
"csi0", "csi0_phy", "csi0_pix", "csi0_rdi" },
|
||||
.clock_rate = { { 0 },
|
||||
{ 40000000, 80000000 },
|
||||
{ 0 },
|
||||
{ 0 },
|
||||
{ 100000000, 200000000 },
|
||||
{ 0 },
|
||||
{ 0 },
|
||||
{ 0 } },
|
||||
.reg = { "csid0" },
|
||||
.interrupt = { "csid0" },
|
||||
.csid = {
|
||||
.hw_ops = &csid_ops_4_1,
|
||||
.parent_dev_ops = &vfe_parent_dev_ops,
|
||||
.formats = &csid_formats_4_1
|
||||
}
|
||||
},
|
||||
|
||||
/* CSID1 */
|
||||
{
|
||||
.regulators = {},
|
||||
.clock = { "top_ahb", "ispif_ahb", "csi1_ahb", "ahb",
|
||||
"csi1", "csi1_phy", "csi1_pix", "csi1_rdi" },
|
||||
.clock_rate = { { 0 },
|
||||
{ 40000000, 80000000 },
|
||||
{ 0 },
|
||||
{ 0 },
|
||||
{ 100000000, 200000000 },
|
||||
{ 0 },
|
||||
{ 0 },
|
||||
{ 0 } },
|
||||
.reg = { "csid1" },
|
||||
.interrupt = { "csid1" },
|
||||
.csid = {
|
||||
.hw_ops = &csid_ops_4_1,
|
||||
.parent_dev_ops = &vfe_parent_dev_ops,
|
||||
.formats = &csid_formats_4_1
|
||||
}
|
||||
},
|
||||
|
||||
/* CSID2 */
|
||||
{
|
||||
.regulators = {},
|
||||
.clock = { "top_ahb", "ispif_ahb", "csi2_ahb", "ahb",
|
||||
"csi2", "csi2_phy", "csi2_pix", "csi2_rdi" },
|
||||
.clock_rate = { { 0 },
|
||||
{ 40000000, 80000000 },
|
||||
{ 0 },
|
||||
{ 0 },
|
||||
{ 100000000, 200000000 },
|
||||
{ 0 },
|
||||
{ 0 },
|
||||
{ 0 } },
|
||||
.reg = { "csid2" },
|
||||
.interrupt = { "csid2" },
|
||||
.csid = {
|
||||
.hw_ops = &csid_ops_4_1,
|
||||
.parent_dev_ops = &vfe_parent_dev_ops,
|
||||
.formats = &csid_formats_4_1
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
static const struct camss_subdev_resources ispif_res_8x39 = {
|
||||
/* ISPIF */
|
||||
.clock = { "top_ahb", "ispif_ahb", "ahb",
|
||||
"csi0", "csi0_pix", "csi0_rdi",
|
||||
"csi1", "csi1_pix", "csi1_rdi",
|
||||
"csi2", "csi2_pix", "csi2_rdi" },
|
||||
.clock_for_reset = { "vfe0", "csi_vfe0" },
|
||||
.reg = { "ispif", "csi_clk_mux" },
|
||||
.interrupt = { "ispif" },
|
||||
};
|
||||
|
||||
static const struct camss_subdev_resources vfe_res_8x39[] = {
|
||||
/* VFE0 */
|
||||
{
|
||||
.regulators = {},
|
||||
.clock = { "top_ahb", "ispif_ahb", "vfe0", "csi_vfe0",
|
||||
"vfe_ahb", "vfe_axi", "ahb" },
|
||||
.clock_rate = { { 0 },
|
||||
{ 40000000, 80000000 },
|
||||
{ 50000000, 80000000, 100000000, 160000000,
|
||||
177780000, 200000000, 266670000, 320000000,
|
||||
400000000, 465000000, 480000000, 600000000 },
|
||||
{ 0 },
|
||||
{ 0 },
|
||||
{ 0 },
|
||||
{ 0 } },
|
||||
.reg = { "vfe0" },
|
||||
.interrupt = { "vfe0" },
|
||||
.vfe = {
|
||||
.line_num = 3,
|
||||
.has_vbif = true,
|
||||
.vbif_name = "vfe0_vbif",
|
||||
.hw_ops = &vfe_ops_4_1,
|
||||
.formats_rdi = &vfe_formats_rdi_8x16,
|
||||
.formats_pix = &vfe_formats_pix_8x16
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
static const struct camss_subdev_resources csid_res_8x53[] = {
|
||||
/* CSID0 */
|
||||
{
|
||||
|
|
@ -4482,6 +4625,7 @@ static int camss_probe(struct platform_device *pdev)
|
|||
return -ENOMEM;
|
||||
|
||||
if (camss->res->version == CAMSS_8x16 ||
|
||||
camss->res->version == CAMSS_8x39 ||
|
||||
camss->res->version == CAMSS_8x53 ||
|
||||
camss->res->version == CAMSS_8x96) {
|
||||
camss->ispif = devm_kcalloc(dev, 1, sizeof(*camss->ispif), GFP_KERNEL);
|
||||
|
|
@ -4613,6 +4757,17 @@ static const struct camss_resources msm8916_resources = {
|
|||
.vfe_num = ARRAY_SIZE(vfe_res_8x16),
|
||||
};
|
||||
|
||||
static const struct camss_resources msm8939_resources = {
|
||||
.version = CAMSS_8x39,
|
||||
.csiphy_res = csiphy_res_8x39,
|
||||
.csid_res = csid_res_8x39,
|
||||
.ispif_res = &ispif_res_8x39,
|
||||
.vfe_res = vfe_res_8x39,
|
||||
.csiphy_num = ARRAY_SIZE(csiphy_res_8x39),
|
||||
.csid_num = ARRAY_SIZE(csid_res_8x39),
|
||||
.vfe_num = ARRAY_SIZE(vfe_res_8x39),
|
||||
};
|
||||
|
||||
static const struct camss_resources msm8953_resources = {
|
||||
.version = CAMSS_8x53,
|
||||
.icc_res = icc_res_8x53,
|
||||
|
|
@ -4793,6 +4948,7 @@ static const struct camss_resources x1e80100_resources = {
|
|||
|
||||
static const struct of_device_id camss_dt_match[] = {
|
||||
{ .compatible = "qcom,msm8916-camss", .data = &msm8916_resources },
|
||||
{ .compatible = "qcom,msm8939-camss", .data = &msm8939_resources },
|
||||
{ .compatible = "qcom,msm8953-camss", .data = &msm8953_resources },
|
||||
{ .compatible = "qcom,msm8996-camss", .data = &msm8996_resources },
|
||||
{ .compatible = "qcom,qcm2290-camss", .data = &qcm2290_resources },
|
||||
|
|
|
|||
|
|
@ -82,6 +82,7 @@ enum camss_version {
|
|||
CAMSS_2290,
|
||||
CAMSS_7280,
|
||||
CAMSS_8x16,
|
||||
CAMSS_8x39,
|
||||
CAMSS_8x53,
|
||||
CAMSS_8x96,
|
||||
CAMSS_8250,
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user