Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 1 addition & 16 deletions arch/arm64/boot/dts/qcom/qcs6490-radxa-cm-q64.dtsi
Original file line number Diff line number Diff line change
Expand Up @@ -845,22 +845,6 @@
"AMIC2", "MIC BIAS2",
"TX SWR_ADC1", "ADC2_OUTPUT";

dp0-dai-link {
link-name = "DP0 Playback";

codec {
sound-dai = <&mdss_dp>;
};

cpu {
sound-dai = <&q6apmbedai DISPLAY_PORT_RX_0>;
};

platform {
sound-dai = <&q6apm>;
};
};

wcd-playback-dai-link {
link-name = "WCD Playback";

Expand Down Expand Up @@ -1142,6 +1126,7 @@
/* For uart_dbg */
&qup_uart5_tx {
bias-disable;
output-high;
drive-strength = <16>;
};

Expand Down
11 changes: 9 additions & 2 deletions drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
Original file line number Diff line number Diff line change
Expand Up @@ -1415,8 +1415,15 @@ static struct msm_display_topology dpu_crtc_get_topology(
else
topology.num_lm = 1;

if (crtc_state->ctm || crtc_state->gamma_lut)
topology.num_dspp = topology.num_lm;
if (crtc_state->ctm || crtc_state->gamma_lut) {
if (topology.num_lm <= (int)dpu_kms->catalog->dspp_count) {
topology.num_dspp = topology.num_lm;
} else {
DRM_WARN("CTM/gamma on %d LM(s) with %d DSPP(s), "
"color management skipped\n",
topology.num_lm, dpu_kms->catalog->dspp_count);
}
}

return topology;
}
Expand Down
8 changes: 6 additions & 2 deletions drivers/gpu/drm/msm/dp/dp_display.c
Original file line number Diff line number Diff line change
Expand Up @@ -986,17 +986,21 @@ static irqreturn_t msm_dp_display_irq_thread(int irq, void *dev_id)
unsigned long flags;
u32 hpd_isr_status;
int rc;
bool was_plugged;

spin_lock_irqsave(&dp->irq_thread_lock, flags);
hpd_isr_status = dp->hpd_isr_status;
dp->hpd_isr_status = 0;
spin_unlock_irqrestore(&dp->irq_thread_lock, flags);

if (hpd_isr_status & DP_DP_HPD_UNPLUG_INT_MASK)
was_plugged = dp->plugged;

/* notify only on actual state transitions */
if (hpd_isr_status & DP_DP_HPD_UNPLUG_INT_MASK && was_plugged)
drm_bridge_hpd_notify(dp->msm_dp_display.bridge,
connector_status_disconnected);

if (hpd_isr_status & DP_DP_HPD_PLUG_INT_MASK)
if (hpd_isr_status & DP_DP_HPD_PLUG_INT_MASK && !was_plugged)
drm_bridge_hpd_notify(dp->msm_dp_display.bridge,
connector_status_connected);

Expand Down
121 changes: 97 additions & 24 deletions drivers/remoteproc/qcom_q6v5_pas.c
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ struct qcom_pas {
int crash_reason_smem;
unsigned int smem_host_id;
bool decrypt_shutdown;
bool preloaded;
const char *info_name;

const struct firmware *firmware;
Expand Down Expand Up @@ -225,6 +226,11 @@ static int qcom_pas_load(struct rproc *rproc, const struct firmware *fw)
struct qcom_pas *pas = rproc->priv;
int ret;

if (pas->preloaded) {
dev_err(pas->dev, "remoteproc is externally managed\n");
return -EPERM;
}

/* Store firmware handle to be used in qcom_pas_start() */
pas->firmware = fw;

Expand Down Expand Up @@ -407,17 +413,23 @@ static int qcom_pas_stop(struct rproc *rproc)
if (ret == -ETIMEDOUT)
dev_err(pas->dev, "timed out on wait\n");

ret = qcom_scm_pas_shutdown(pas->pas_id);
if (ret && pas->decrypt_shutdown)
ret = qcom_pas_shutdown_poll_decrypt(pas);
if (pas->preloaded) {
ret = 0;
} else {
ret = qcom_scm_pas_shutdown(pas->pas_id);
if (ret && pas->decrypt_shutdown)
ret = qcom_pas_shutdown_poll_decrypt(pas);

if (ret)
dev_err(pas->dev, "failed to shutdown: %d\n", ret);
if (ret)
dev_err(pas->dev, "failed to shutdown: %d\n", ret);
}

if (pas->dtb_pas_id) {
ret = qcom_scm_pas_shutdown(pas->dtb_pas_id);
if (ret)
dev_err(pas->dev, "failed to shutdown dtb: %d\n", ret);
if (!pas->preloaded) {
ret = qcom_scm_pas_shutdown(pas->dtb_pas_id);
if (ret)
dev_err(pas->dev, "failed to shutdown dtb: %d\n", ret);
}

qcom_pas_unmap_carveout(rproc, pas->dtb_mem_phys, pas->dtb_mem_size);
}
Expand Down Expand Up @@ -517,16 +529,65 @@ static unsigned long qcom_pas_panic(struct rproc *rproc)
return qcom_q6v5_panic(&pas->q6v5);
}

static int qcom_pas_get_boot_state_from_smp2p(struct qcom_pas *pas,
bool *ready_state,
bool *crash_state)
{
bool handover = false;
bool ready = false;
bool fatal = false;
bool stop = false;
int ret;

ret = irq_get_irqchip_state(pas->q6v5.handover_irq,
IRQCHIP_STATE_LINE_LEVEL, &handover);
if (ret)
return ret;

ret = irq_get_irqchip_state(pas->q6v5.ready_irq,
IRQCHIP_STATE_LINE_LEVEL, &ready);
if (ret)
return ret;

ret = irq_get_irqchip_state(pas->q6v5.fatal_irq,
IRQCHIP_STATE_LINE_LEVEL, &fatal);
if (ret)
return ret;

ret = irq_get_irqchip_state(pas->q6v5.stop_irq,
IRQCHIP_STATE_LINE_LEVEL, &stop);
if (ret)
return ret;

*crash_state = fatal;
*ready_state = ready && handover && !stop && !fatal;

return 0;
}

static int qcom_pas_attach(struct rproc *rproc)
{
int ret;
struct qcom_pas *pas = rproc->priv;
bool ready_state;
bool crash_state;
bool ready_state = false;
bool crash_state = false;

pas->q6v5.running = true;
ret = irq_get_irqchip_state(pas->q6v5.fatal_irq,
IRQCHIP_STATE_LINE_LEVEL, &crash_state);

if (pas->preloaded) {
ret = qcom_pas_get_boot_state_from_smp2p(pas,
&ready_state,
&crash_state);
} else {
ret = irq_get_irqchip_state(pas->q6v5.fatal_irq,
IRQCHIP_STATE_LINE_LEVEL,
&crash_state);

if (!ret && !crash_state)
ret = irq_get_irqchip_state(pas->q6v5.ready_irq,
IRQCHIP_STATE_LINE_LEVEL,
&ready_state);
}

if (ret)
goto disable_running;
Expand All @@ -538,30 +599,28 @@ static int qcom_pas_attach(struct rproc *rproc)
goto disable_running;
}

ret = irq_get_irqchip_state(pas->q6v5.ready_irq,
IRQCHIP_STATE_LINE_LEVEL, &ready_state);

if (ret)
goto disable_running;

if (unlikely(!ready_state)) {
/*
* The bootloader may not support early boot, mark the state as
* RPROC_OFFLINE so that the PAS driver can load the firmware and
* start the remoteproc.
*/
dev_err(pas->dev, "Failed to get subsystem ready interrupt\n");
dev_err(pas->dev, pas->preloaded ?
"Failed to detect already running subsystem\n" :
"Failed to get subsystem ready interrupt\n");
pas->rproc->state = RPROC_OFFLINE;
ret = -EINVAL;
goto disable_running;
}

ret = qcom_q6v5_ping_subsystem(&pas->q6v5);
if (!pas->preloaded) {
ret = qcom_q6v5_ping_subsystem(&pas->q6v5);

if (ret) {
dev_err(pas->dev, "Failed to ping subsystem, assuming device crashed\n");
rproc_report_crash(rproc, RPROC_FATAL_ERROR);
goto disable_running;
if (ret) {
dev_err(pas->dev, "Failed to ping subsystem, assuming device crashed\n");
rproc_report_crash(rproc, RPROC_FATAL_ERROR);
goto disable_running;
}
}

pas->q6v5.handover_issued = true;
Expand Down Expand Up @@ -805,6 +864,8 @@ static int qcom_pas_probe(struct platform_device *pdev)
struct rproc *rproc;
const char *fw_name, *dtb_fw_name = NULL;
const struct rproc_ops *ops = &qcom_pas_ops;
bool ready_state;
bool crash_state;
int ret;

desc = of_device_get_match_data(&pdev->dev);
Expand Down Expand Up @@ -852,6 +913,7 @@ static int qcom_pas_probe(struct platform_device *pdev)
pas->info_name = desc->sysmon_name;
pas->smem_host_id = desc->smem_host_id;
pas->decrypt_shutdown = desc->decrypt_shutdown;
pas->preloaded = false;
pas->region_assign_idx = desc->region_assign_idx;
pas->region_assign_count = min_t(int, MAX_ASSIGN_COUNT, desc->region_assign_count);
pas->region_assign_vmid = desc->region_assign_vmid;
Expand Down Expand Up @@ -927,6 +989,17 @@ static int qcom_pas_probe(struct platform_device *pdev)
dev_warn(&pdev->dev, "Falling back to firmware load\n");
else
pas->rproc->state = RPROC_DETACHED;
} else {
ret = qcom_pas_get_boot_state_from_smp2p(pas,
&ready_state,
&crash_state);
if (ret) {
dev_warn(&pdev->dev, "Failed to read SMP2P state; falling back to firmware load\n");
} else if (ready_state) {
pas->preloaded = true;
pas->rproc->state = RPROC_DETACHED;
rproc_set_feature(pas->rproc, RPROC_FEAT_ATTACH_ON_RECOVERY);
}
}

ret = rproc_add(rproc);
Expand Down