Re: [PATCH] drm: Replace drm_modeset_lock/unlock_all with DRM_MODESET_LOCK_ALL_* helpers
On 29.04.2020 10:57, Jani Nikula wrote: > On Tue, 28 Apr 2020, Michal Orzel wrote: >> As suggested by the TODO list for the kernel DRM subsystem, replace >> the deprecated functions that take/drop modeset locks with new helpers. >> >> Signed-off-by: Michal Orzel >> --- >> drivers/gpu/drm/drm_mode_object.c | 10 ++ >> 1 file changed, 6 insertions(+), 4 deletions(-) >> >> diff --git a/drivers/gpu/drm/drm_mode_object.c >> b/drivers/gpu/drm/drm_mode_object.c >> index 35c2719..901b078 100644 >> --- a/drivers/gpu/drm/drm_mode_object.c >> +++ b/drivers/gpu/drm/drm_mode_object.c >> @@ -402,12 +402,13 @@ int drm_mode_obj_get_properties_ioctl(struct >> drm_device *dev, void *data, >> { >> struct drm_mode_obj_get_properties *arg = data; >> struct drm_mode_object *obj; >> +struct drm_modeset_acquire_ctx ctx; >> int ret = 0; >> >> if (!drm_core_check_feature(dev, DRIVER_MODESET)) >> return -EOPNOTSUPP; >> >> -drm_modeset_lock_all(dev); >> +DRM_MODESET_LOCK_ALL_BEGIN(dev, ctx, 0, ret); > > I cry a little every time I look at the DRM_MODESET_LOCK_ALL_BEGIN and > DRM_MODESET_LOCK_ALL_END macros. :( > > Currently only six users... but there are ~60 calls to > drm_modeset_lock_all{,_ctx} that I presume are to be replaced. I wonder > if this will come back and haunt us. > > BR, > Jani. Hm, so we can either replace all of these calls(I think it's a better option) or abandon the idea of removing this deprecated function. In the latter scenario, it'd be beneficial to remove this from TODO. Best regards Michal > > >> >> obj = drm_mode_object_find(dev, file_priv, arg->obj_id, arg->obj_type); >> if (!obj) { >> @@ -427,7 +428,7 @@ int drm_mode_obj_get_properties_ioctl(struct drm_device >> *dev, void *data, >> out_unref: >> drm_mode_object_put(obj); >> out: >> -drm_modeset_unlock_all(dev); >> +DRM_MODESET_LOCK_ALL_END(ctx, ret); >> return ret; >> } >> >> @@ -449,12 +450,13 @@ static int set_property_legacy(struct drm_mode_object >> *obj, >> { >> struct drm_device *dev = prop->dev; >> struct drm_mode_object *ref; >> +struct drm_modeset_acquire_ctx ctx; >> int ret = -EINVAL; >> >> if (!drm_property_change_valid_get(prop, prop_value, )) >> return -EINVAL; >> >> -drm_modeset_lock_all(dev); >> +DRM_MODESET_LOCK_ALL_BEGIN(dev, ctx, 0, ret); >> switch (obj->type) { >> case DRM_MODE_OBJECT_CONNECTOR: >> ret = drm_connector_set_obj_prop(obj, prop, prop_value); >> @@ -468,7 +470,7 @@ static int set_property_legacy(struct drm_mode_object >> *obj, >> break; >> } >> drm_property_change_valid_put(prop, ref); >> -drm_modeset_unlock_all(dev); >> +DRM_MODESET_LOCK_ALL_END(ctx, ret); >> >> return ret; >> } > ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [PATCH] dma-buf: Documentation: fix: `make htmldocs` warnings
On Wed, Apr 29, 2020 at 11:27:22PM -0300, Vitor Massaru Iha wrote: > On Wed, 2020-04-29 at 19:06 -0700, Randy Dunlap wrote: > > On 4/29/20 6:59 PM, Vitor Massaru Iha wrote: > > > Add missed ":" on kernel-doc function parameter. > > > > > > This patch fixes this warnings from `make htmldocs`: > > > ./drivers/dma-buf/dma-buf.c:678: warning: Function parameter or > > > member 'importer_ops' not described in 'dma_buf_dynamic_attach' > > > ./drivers/dma-buf/dma-buf.c:678: warning: Function parameter or > > > member 'importer_priv' not described in 'dma_buf_dynamic_attach' > > > > > > Signed-off-by: Vitor Massaru Iha > > > --- > > > drivers/dma-buf/dma-buf.c | 4 ++-- > > > 1 file changed, 2 insertions(+), 2 deletions(-) > > > > > > diff --git a/drivers/dma-buf/dma-buf.c b/drivers/dma-buf/dma-buf.c > > > index ccc9eda1bc28..0756d2155745 100644 > > > --- a/drivers/dma-buf/dma-buf.c > > > +++ b/drivers/dma-buf/dma-buf.c > > > @@ -655,8 +655,8 @@ EXPORT_SYMBOL_GPL(dma_buf_put); > > > * calls attach() of dma_buf_ops to allow device-specific attach > > > functionality > > > * @dmabuf: [in]buffer to attach device to. > > > * @dev: [in]device to be attached. > > > - * @importer_ops [in]importer operations for the > > > attachment > > > - * @importer_priv[in]importer private pointer for the > > > attachment > > > + * @importer_ops:[in]importer operations for the > > > attachment > > > + * @importer_priv: [in]importer private pointer for the > > > attachment > > > * > > > * Returns struct dma_buf_attachment pointer for this attachment. > > > Attachments > > > * must be cleaned up by calling dma_buf_detach(). > > > > > > > Sumit said that he would be applying my patch from April 7: > > https://lore.kernel.org/linux-media/7bcbe6fe-0b4b-87da-d003-b68a26eb4...@infradead.org/ > > > > thanks. > > Sorry. I didn't check if the patch has already been sent. Sumit - patch from Randy is neither applied to drm-misc-next nor drm-misc-fixes. A reminder in case it was lost somewhere. Sam ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [Nouveau] [PATCH] drm/nouveau: Fix regression by audio component transition
Good catch! The OR is definitely a far better choice than the head here, as it's what we use to select the GPU-side HDA registers too. Merged. On Thu, 16 Apr 2020 at 17:54, Takashi Iwai wrote: > > Since the commit 742db30c4ee6 ("drm/nouveau: Add HD-audio component > notifier support"), the nouveau driver notifies and pokes the HD-audio > HPD and ELD via audio component, but this seems broken. The culprit > is the naive assumption that crtc->index corresponds to the HDA pin. > Actually this rather corresponds to the MST dev_id (alias "pipe" in > the audio component framework) while the actual port number is given > from the output ior id number. > > This patch corrects the assignment of port and dev_id arguments in the > audio component ops to recover from the HDMI/DP audio regression. > > Fixes: 742db30c4ee6 ("drm/nouveau: Add HD-audio component notifier support") > BugLink: https://bugzilla.kernel.org/show_bug.cgi?id=207223 > Cc: > Signed-off-by: Takashi Iwai > --- > drivers/gpu/drm/nouveau/dispnv50/disp.c | 16 ++-- > 1 file changed, 10 insertions(+), 6 deletions(-) > > diff --git a/drivers/gpu/drm/nouveau/dispnv50/disp.c > b/drivers/gpu/drm/nouveau/dispnv50/disp.c > index a3dc2ba19fb2..3a9fd565079d 100644 > --- a/drivers/gpu/drm/nouveau/dispnv50/disp.c > +++ b/drivers/gpu/drm/nouveau/dispnv50/disp.c > @@ -481,15 +481,16 @@ nv50_dac_create(struct drm_connector *connector, struct > dcb_output *dcbe) > * audio component binding for ELD notification > */ > static void > -nv50_audio_component_eld_notify(struct drm_audio_component *acomp, int port) > +nv50_audio_component_eld_notify(struct drm_audio_component *acomp, int port, > + int dev_id) > { > if (acomp && acomp->audio_ops && acomp->audio_ops->pin_eld_notify) > acomp->audio_ops->pin_eld_notify(acomp->audio_ops->audio_ptr, > -port, -1); > +port, dev_id); > } > > static int > -nv50_audio_component_get_eld(struct device *kdev, int port, int pipe, > +nv50_audio_component_get_eld(struct device *kdev, int port, int dev_id, > bool *enabled, unsigned char *buf, int max_bytes) > { > struct drm_device *drm_dev = dev_get_drvdata(kdev); > @@ -505,7 +506,8 @@ nv50_audio_component_get_eld(struct device *kdev, int > port, int pipe, > nv_encoder = nouveau_encoder(encoder); > nv_connector = nouveau_encoder_connector_get(nv_encoder); > nv_crtc = nouveau_crtc(encoder->crtc); > - if (!nv_connector || !nv_crtc || nv_crtc->index != port) > + if (!nv_connector || !nv_crtc || nv_encoder->or != port || > + nv_crtc->index != dev_id) > continue; > *enabled = drm_detect_monitor_audio(nv_connector->edid); > if (*enabled) { > @@ -599,7 +601,8 @@ nv50_audio_disable(struct drm_encoder *encoder, struct > nouveau_crtc *nv_crtc) > > nvif_mthd(>disp->object, 0, , sizeof(args)); > > - nv50_audio_component_eld_notify(drm->audio.component, nv_crtc->index); > + nv50_audio_component_eld_notify(drm->audio.component, nv_encoder->or, > + nv_crtc->index); > } > > static void > @@ -633,7 +636,8 @@ nv50_audio_enable(struct drm_encoder *encoder, struct > drm_display_mode *mode) > nvif_mthd(>disp->object, 0, , > sizeof(args.base) + drm_eld_size(args.data)); > > - nv50_audio_component_eld_notify(drm->audio.component, nv_crtc->index); > + nv50_audio_component_eld_notify(drm->audio.component, nv_encoder->or, > + nv_crtc->index); > } > > > /** > -- > 2.16.4 > > ___ > Nouveau mailing list > nouv...@lists.freedesktop.org > https://lists.freedesktop.org/mailman/listinfo/nouveau ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH v2] dt-bindings: arm-smmu: Add sc7180 compatible string and mem_iface clock
This patch adds a new compatible string for sc7180 and also an additional clock listing needed to power the TBUs and the TCU. Signed-off-by: Sharat Masetty --- v2: Addressed review comments from Doug Documentation/devicetree/bindings/iommu/arm,smmu.yaml | 8 1 file changed, 8 insertions(+) diff --git a/Documentation/devicetree/bindings/iommu/arm,smmu.yaml b/Documentation/devicetree/bindings/iommu/arm,smmu.yaml index 6515dbe..ba5dba4 100644 --- a/Documentation/devicetree/bindings/iommu/arm,smmu.yaml +++ b/Documentation/devicetree/bindings/iommu/arm,smmu.yaml @@ -28,6 +28,7 @@ properties: - enum: - qcom,msm8996-smmu-v2 - qcom,msm8998-smmu-v2 + - qcom,sc7180-smmu-v2 - qcom,sdm845-smmu-v2 - const: qcom,smmu-v2 @@ -113,16 +114,23 @@ properties: present in such cases. clock-names: +minItems: 2 +maxItems: 3 items: - const: bus - const: iface + - const: mem_iface clocks: +minItems: 2 +maxItems: 3 items: - description: bus clock required for downstream bus access and for the smmu ptw - description: interface clock required to access smmu's registers through the TCU's programming interface. + - description: clock required for the inner working of SMMU TBUs and the + TCU like the pagetable walks and the TLB flushes. power-domains: maxItems: 1 -- 1.9.1 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [Nouveau] [PATCH] drm/nouveau/mmu: Remove unneeded semicolon
Thanks! On Fri, 24 Apr 2020 at 17:29, Zheng Bin wrote: > > Fixes coccicheck warning: > > drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmm.h:307:2-3: Unneeded semicolon > drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmm.c:583:2-3: Unneeded semicolon > > Reported-by: Hulk Robot > Signed-off-by: Zheng Bin > --- > drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmm.c | 2 +- > drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmm.h | 2 +- > 2 files changed, 2 insertions(+), 2 deletions(-) > > diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmm.c > b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmm.c > index 41640e0584ac..199f94e15c5f 100644 > --- a/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmm.c > +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmm.c > @@ -580,7 +580,7 @@ nvkm_vmm_iter(struct nvkm_vmm *vmm, const struct > nvkm_vmm_page *page, > it.pte[it.lvl]++; > } > } > - }; > + } > > nvkm_vmm_flush(); > return ~0ULL; > diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmm.h > b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmm.h > index 5e55ecbd8005..d3f8f916d0db 100644 > --- a/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmm.h > +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmm.h > @@ -304,7 +304,7 @@ int tu102_vmm_new(struct nvkm_mmu *, bool, u64, u64, void > *, u32, > FILL(VMM, PT, PTEI, _ptes, MAP, _addr); > \ > PTEI += _ptes; > \ > PTEN -= _ptes; > \ > - }; > \ > + } > \ > nvkm_done((PT)->memory); > \ > } while(0) > > -- > 2.26.0.106.g9fadedd > > ___ > Nouveau mailing list > nouv...@lists.freedesktop.org > https://lists.freedesktop.org/mailman/listinfo/nouveau ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [PATCH 1/1] drm/nouveau: Use generic helper to check _PR3 presence
Thanks! On Thu, 23 Apr 2020 at 17:37, Kai-Heng Feng wrote: > > Replace nouveau_pr3_present() in favor of a more generic one, > pci_pr3_present(). > > Also the presence of upstream bridge _PR3 doesn't need to go hand in > hand with device's _DSM, so check _PR3 before _DSM. > > Signed-off-by: Kai-Heng Feng > --- > drivers/gpu/drm/nouveau/nouveau_acpi.c | 44 ++ > 1 file changed, 10 insertions(+), 34 deletions(-) > > diff --git a/drivers/gpu/drm/nouveau/nouveau_acpi.c > b/drivers/gpu/drm/nouveau/nouveau_acpi.c > index fe3a10255c36..b84dff1b0f28 100644 > --- a/drivers/gpu/drm/nouveau/nouveau_acpi.c > +++ b/drivers/gpu/drm/nouveau/nouveau_acpi.c > @@ -212,37 +212,6 @@ static const struct vga_switcheroo_handler > nouveau_dsm_handler = { > .get_client_id = nouveau_dsm_get_client_id, > }; > > -/* > - * Firmware supporting Windows 8 or later do not use _DSM to put the device > into > - * D3cold, they instead rely on disabling power resources on the parent. > - */ > -static bool nouveau_pr3_present(struct pci_dev *pdev) > -{ > - struct pci_dev *parent_pdev = pci_upstream_bridge(pdev); > - struct acpi_device *parent_adev; > - > - if (!parent_pdev) > - return false; > - > - if (!parent_pdev->bridge_d3) { > - /* > -* Parent PCI bridge is currently not power managed. > -* Since userspace can change these afterwards to be on > -* the safe side we stick with _DSM and prevent usage of > -* _PR3 from the bridge. > -*/ > - pci_d3cold_disable(pdev); > - return false; > - } > - > - parent_adev = ACPI_COMPANION(_pdev->dev); > - if (!parent_adev) > - return false; > - > - return parent_adev->power.flags.power_resources && > - acpi_has_method(parent_adev->handle, "_PR3"); > -} > - > static void nouveau_dsm_pci_probe(struct pci_dev *pdev, acpi_handle > *dhandle_out, > bool *has_mux, bool *has_opt, > bool *has_opt_flags, bool *has_pr3) > @@ -250,6 +219,16 @@ static void nouveau_dsm_pci_probe(struct pci_dev *pdev, > acpi_handle *dhandle_out > acpi_handle dhandle; > bool supports_mux; > int optimus_funcs; > + struct pci_dev *parent_pdev; > + > + *has_pr3 = false; > + parent_pdev = pci_upstream_bridge(pdev); > + if (parent_pdev) { > + if (parent_pdev->bridge_d3) > + *has_pr3 = pci_pr3_present(parent_pdev); > + else > + pci_d3cold_disable(pdev); > + } > > dhandle = ACPI_HANDLE(>dev); > if (!dhandle) > @@ -270,7 +249,6 @@ static void nouveau_dsm_pci_probe(struct pci_dev *pdev, > acpi_handle *dhandle_out > *has_mux = supports_mux; > *has_opt = !!optimus_funcs; > *has_opt_flags = optimus_funcs & (1 << NOUVEAU_DSM_OPTIMUS_FLAGS); > - *has_pr3 = false; > > if (optimus_funcs) { > uint32_t result; > @@ -280,8 +258,6 @@ static void nouveau_dsm_pci_probe(struct pci_dev *pdev, > acpi_handle *dhandle_out > (result & OPTIMUS_ENABLED) ? "enabled" : "disabled", > (result & OPTIMUS_DYNAMIC_PWR_CAP) ? "dynamic power, > " : "", > (result & OPTIMUS_HDA_CODEC_MASK) ? "hda bios codec > supported" : ""); > - > - *has_pr3 = nouveau_pr3_present(pdev); > } > } > > -- > 2.17.1 > > ___ > dri-devel mailing list > dri-devel@lists.freedesktop.org > https://lists.freedesktop.org/mailman/listinfo/dri-devel ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [PATCH -next] drm/nouveau/acr: Use kmemdup instead of kmalloc and memcpy
Thanks! On Wed, 22 Apr 2020 at 16:56, Zou Wei wrote: > > Fixes coccicheck warning: > > drivers/gpu/drm/nouveau/nvkm/subdev/acr/hsfw.c:103:23-30: WARNING opportunity > for kmemdup > drivers/gpu/drm/nouveau/nvkm/subdev/acr/hsfw.c:113:22-29: WARNING opportunity > for kmemdup > > Fixes: 22dcda45a3d1 ("drm/nouveau/acr: implement new subdev to replace > "secure boot"") > Reported-by: Hulk Robot > Signed-off-by: Zou Wei > --- > drivers/gpu/drm/nouveau/nvkm/subdev/acr/hsfw.c | 12 > 1 file changed, 4 insertions(+), 8 deletions(-) > > diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/acr/hsfw.c > b/drivers/gpu/drm/nouveau/nvkm/subdev/acr/hsfw.c > index aecce2d..667fa01 100644 > --- a/drivers/gpu/drm/nouveau/nvkm/subdev/acr/hsfw.c > +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/acr/hsfw.c > @@ -100,25 +100,21 @@ nvkm_acr_hsfw_load_image(struct nvkm_acr *acr, const > char *name, int ver, > hsfw->data_size = lhdr->data_size; > > hsfw->sig.prod.size = fwhdr->sig_prod_size; > - hsfw->sig.prod.data = kmalloc(hsfw->sig.prod.size, GFP_KERNEL); > + hsfw->sig.prod.data = kmemdup(fw->data + fwhdr->sig_prod_offset + sig, > + hsfw->sig.prod.size, GFP_KERNEL); > if (!hsfw->sig.prod.data) { > ret = -ENOMEM; > goto done; > } > > - memcpy(hsfw->sig.prod.data, fw->data + fwhdr->sig_prod_offset + sig, > - hsfw->sig.prod.size); > - > hsfw->sig.dbg.size = fwhdr->sig_dbg_size; > - hsfw->sig.dbg.data = kmalloc(hsfw->sig.dbg.size, GFP_KERNEL); > + hsfw->sig.dbg.data = kmemdup(fw->data + fwhdr->sig_dbg_offset + sig, > +hsfw->sig.dbg.size, GFP_KERNEL); > if (!hsfw->sig.dbg.data) { > ret = -ENOMEM; > goto done; > } > > - memcpy(hsfw->sig.dbg.data, fw->data + fwhdr->sig_dbg_offset + sig, > - hsfw->sig.dbg.size); > - > hsfw->sig.patch_loc = loc; > done: > nvkm_firmware_put(fw); > -- > 2.6.2 > > ___ > dri-devel mailing list > dri-devel@lists.freedesktop.org > https://lists.freedesktop.org/mailman/listinfo/dri-devel ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [PATCH] dma-buf: Documentation: fix: `make htmldocs` warnings
On Wed, 2020-04-29 at 19:06 -0700, Randy Dunlap wrote: > On 4/29/20 6:59 PM, Vitor Massaru Iha wrote: > > Add missed ":" on kernel-doc function parameter. > > > > This patch fixes this warnings from `make htmldocs`: > > ./drivers/dma-buf/dma-buf.c:678: warning: Function parameter or > > member 'importer_ops' not described in 'dma_buf_dynamic_attach' > > ./drivers/dma-buf/dma-buf.c:678: warning: Function parameter or > > member 'importer_priv' not described in 'dma_buf_dynamic_attach' > > > > Signed-off-by: Vitor Massaru Iha > > --- > > drivers/dma-buf/dma-buf.c | 4 ++-- > > 1 file changed, 2 insertions(+), 2 deletions(-) > > > > diff --git a/drivers/dma-buf/dma-buf.c b/drivers/dma-buf/dma-buf.c > > index ccc9eda1bc28..0756d2155745 100644 > > --- a/drivers/dma-buf/dma-buf.c > > +++ b/drivers/dma-buf/dma-buf.c > > @@ -655,8 +655,8 @@ EXPORT_SYMBOL_GPL(dma_buf_put); > > * calls attach() of dma_buf_ops to allow device-specific attach > > functionality > > * @dmabuf:[in]buffer to attach device to. > > * @dev: [in]device to be attached. > > - * @importer_ops [in]importer operations for the > > attachment > > - * @importer_priv [in]importer private pointer for the > > attachment > > + * @importer_ops: [in]importer operations for the > > attachment > > + * @importer_priv: [in]importer private pointer for the > > attachment > > * > > * Returns struct dma_buf_attachment pointer for this attachment. > > Attachments > > * must be cleaned up by calling dma_buf_detach(). > > > > Sumit said that he would be applying my patch from April 7: > https://lore.kernel.org/linux-media/7bcbe6fe-0b4b-87da-d003-b68a26eb4...@infradead.org/ > > thanks. Sorry. I didn't check if the patch has already been sent. ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH] dma-buf: Documentation: fix: `make htmldocs` warnings
Add missed ":" on kernel-doc function parameter. This patch fixes this warnings from `make htmldocs`: ./drivers/dma-buf/dma-buf.c:678: warning: Function parameter or member 'importer_ops' not described in 'dma_buf_dynamic_attach' ./drivers/dma-buf/dma-buf.c:678: warning: Function parameter or member 'importer_priv' not described in 'dma_buf_dynamic_attach' Signed-off-by: Vitor Massaru Iha --- drivers/dma-buf/dma-buf.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/dma-buf/dma-buf.c b/drivers/dma-buf/dma-buf.c index ccc9eda1bc28..0756d2155745 100644 --- a/drivers/dma-buf/dma-buf.c +++ b/drivers/dma-buf/dma-buf.c @@ -655,8 +655,8 @@ EXPORT_SYMBOL_GPL(dma_buf_put); * calls attach() of dma_buf_ops to allow device-specific attach functionality * @dmabuf:[in]buffer to attach device to. * @dev: [in]device to be attached. - * @importer_ops [in]importer operations for the attachment - * @importer_priv [in]importer private pointer for the attachment + * @importer_ops: [in]importer operations for the attachment + * @importer_priv: [in]importer private pointer for the attachment * * Returns struct dma_buf_attachment pointer for this attachment. Attachments * must be cleaned up by calling dma_buf_detach(). -- 2.25.1 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [PATCH 1/1] drm/mm: optimize rb_hole_addr rbtree search in high addr mode
Hi Nirmoy, Thank you for the patch! Perhaps something to improve: [auto build test WARNING on drm-intel/for-linux-next] [also build test WARNING on drm-exynos/exynos-drm-next tegra-drm/drm/tegra/for-next drm-tip/drm-tip linus/master v5.7-rc3 next-20200429] [cannot apply to drm/drm-next] [if your patch is applied to the wrong git tree, please drop us a note to help improve the system. BTW, we also suggest to use '--base' option to specify the base tree in git format-patch, please see https://stackoverflow.com/a/37406982] url: https://github.com/0day-ci/linux/commits/Nirmoy-Das/drm-mm-optimize-rb_hole_addr-rbtree-search-in-high-addr-mode/20200429-154950 base: git://anongit.freedesktop.org/drm-intel for-linux-next reproduce: # apt-get install sparse # sparse version: v0.6.1-191-gc51a0382-dirty make ARCH=x86_64 allmodconfig make C=1 CF='-fdiagnostic-prefix -D__CHECK_ENDIAN__' If you fix the issue, kindly add following tag as appropriate Reported-by: kbuild test robot sparse warnings: (new ones prefixed by >>) >> drivers/gpu/drm/drm_mm.c:455:24: sparse: sparse: Using plain integer as NULL >> pointer vim +455 drivers/gpu/drm/drm_mm.c 431 432 /** 433 * next_hole_high_addr - returns next hole for a DRM_MM_INSERT_HIGH mode request 434 * @entry: previously selected drm_mm_node 435 * @size: size of the a hole needed for the request 436 * 437 * This function will verify whether left subtree of @entry has hole big enough 438 * to fit the requtested size. If so, it will return previous node of @entry or 439 * else it will return parent node of @entry 440 * 441 * It will also skip the complete left subtree if max_hole_size of that subtree 442 * is same as the max_hole_size of the @entry. 443 * 444 * Returns: 445 * previous node of @entry if left subtree of @entry can serve the request or 446 * else return parent of @entry 447 */ 448 static struct drm_mm_node * 449 next_hole_high_addr(struct drm_mm_node *entry, u64 size) 450 { 451 struct rb_node *rb_node, *left_rb_node, *parent_rb_node; 452 struct drm_mm_node *left_node; 453 454 if (!entry) > 455 return false; 456 457 rb_node = >rb_hole_addr; 458 if (rb_node->rb_left) { 459 left_rb_node = rb_node->rb_left; 460 parent_rb_node = rb_parent(rb_node); 461 left_node = rb_entry(left_rb_node, 462 struct drm_mm_node, rb_hole_addr); 463 if ((left_node->max_hole_size < size || 464 entry->size == entry->max_hole_size) && 465 parent_rb_node && parent_rb_node->rb_left != rb_node) 466 return rb_hole_addr_to_node(parent_rb_node); 467 } 468 469 return rb_hole_addr_to_node(rb_prev(rb_node)); 470 } 471 --- 0-DAY CI Kernel Test Service, Intel Corporation https://lists.01.org/hyperkitty/list/kbuild-...@lists.01.org ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[pull] amdgpu drm-fixes-5.7
Hi Dave, Daniel, Fixes for 5.7. The following changes since commit e32b2484b3e00170b6cf57d99a18972e174e10ea: Merge tag 'drm-misc-fixes-2020-04-23' of git://anongit.freedesktop.org/drm/drm-misc into drm-fixes (2020-04-24 10:14:04 +1000) are available in the Git repository at: git://people.freedesktop.org/~agd5f/linux tags/amd-drm-fixes-5.7-2020-04-29 for you to fetch changes up to b2a7b0ce0773bfa4406bc0a78e41979532a1edd7: drm/amd/display: Use cursor locking to prevent flip delays (2020-04-28 16:45:14 -0400) amd-drm-fixes-5.7-2020-04-29: amdgpu: - Fix a green screen on resume issue - PM fixes for SR-IOV - SDMA fix for navi - Renoir display fixes - Cursor and pageflip stuttering fixes - Misc additional display fixes UAPI: - Add additional DCC tiling flags for navi1x Used by: https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/4697 Aric Cyr (1): drm/amd/display: Use cursor locking to prevent flip delays Aurabindo Pillai (1): drm/amd/display: DispalyPort: Write OUI only if panel supports it Dmytro Laktyushkin (2): drm/amd/display: check if REFCLK_CNTL register is present drm/amd/display: fix rn soc bb update Marek Olšák (3): drm/amdgpu: add tiling flags from Mesa drm/amdgpu: invalidate L2 before SDMA IBs (v2) drm/amdgpu: bump version for invalidate L2 before SDMA IBs Nicholas Kazlauskas (1): drm/amd/display: Defer cursor update around VUPDATE for all ASIC Rodrigo Siqueira (1): drm/amd/display: Fix green screen issue after suspend Sung Lee (1): drm/amd/display: Update downspread percent to match spreadsheet for DCN2.1 Tiecheng Zhou (2): Revert "drm/amd/powerplay: avoid using pm_en before it is initialized" drm/amd/powerplay: avoid using pm_en before it is initialized revised Xiaodong Yan (1): drm/amd/display: blank dp stream before re-train the link drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c| 3 +- drivers/gpu/drm/amd/amdgpu/navi10_sdma_pkt_open.h | 16 + drivers/gpu/drm/amd/amdgpu/sdma_v5_0.c | 14 +++- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 38 --- drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c | 27 drivers/gpu/drm/amd/display/dc/core/dc_stream.c| 40 ++- .../amd/display/dc/dce110/dce110_hw_sequencer.c| 1 + .../drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c | 10 +++ .../drm/amd/display/dc/dcn10/dcn10_hw_sequencer.h | 1 + drivers/gpu/drm/amd/display/dc/dcn10/dcn10_init.c | 1 + drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.c | 15 + drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.h | 20 -- .../gpu/drm/amd/display/dc/dcn10/dcn10_resource.c | 14 +++- drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c | 3 +- drivers/gpu/drm/amd/display/dc/dcn20/dcn20_init.c | 1 + drivers/gpu/drm/amd/display/dc/dcn20/dcn20_mpc.c | 1 + drivers/gpu/drm/amd/display/dc/dcn20/dcn20_mpc.h | 3 +- .../gpu/drm/amd/display/dc/dcn20/dcn20_resource.c | 4 ++ drivers/gpu/drm/amd/display/dc/dcn21/dcn21_init.c | 1 + .../gpu/drm/amd/display/dc/dcn21/dcn21_resource.c | 77 ++ drivers/gpu/drm/amd/display/dc/inc/hw/mpc.h| 16 + drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h | 1 + drivers/gpu/drm/amd/powerplay/amd_powerplay.c | 9 +-- include/uapi/drm/amdgpu_drm.h | 4 ++ 24 files changed, 215 insertions(+), 105 deletions(-) ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [PATCH] drm/bridge: fix stack usage warning on old gcc
Hi Arnd. On Tue, Apr 28, 2020 at 11:53:54PM +0200, Arnd Bergmann wrote: > Some older versions of gcc badly optimize code that passes > an inline function argument into another function by reference, > causing huge stack usage: > > drivers/gpu/drm/bridge/tc358768.c: In function 'tc358768_bridge_pre_enable': > drivers/gpu/drm/bridge/tc358768.c:840:1: error: the frame size of 2256 bytes > is larger than 2048 bytes [-Werror=frame-larger-than=] > > Use a temporary variable as a workaround and add a comment pointing > to the gcc bug. > > Fixes: ff1ca6397b1d ("drm/bridge: Add tc358768 driver") > Signed-off-by: Arnd Bergmann Thanks, pushed to drm-misc-next with Tomi's r-b. Sam > --- > drivers/gpu/drm/bridge/tc358768.c | 4 +++- > 1 file changed, 3 insertions(+), 1 deletion(-) > > diff --git a/drivers/gpu/drm/bridge/tc358768.c > b/drivers/gpu/drm/bridge/tc358768.c > index 1b39e8d37834..6650fe4cfc20 100644 > --- a/drivers/gpu/drm/bridge/tc358768.c > +++ b/drivers/gpu/drm/bridge/tc358768.c > @@ -178,6 +178,8 @@ static int tc358768_clear_error(struct tc358768_priv > *priv) > > static void tc358768_write(struct tc358768_priv *priv, u32 reg, u32 val) > { > + /* work around https://gcc.gnu.org/bugzilla/show_bug.cgi?id=81715 */ > + int tmpval = val; > size_t count = 2; > > if (priv->error) > @@ -187,7 +189,7 @@ static void tc358768_write(struct tc358768_priv *priv, > u32 reg, u32 val) > if (reg < 0x100 || reg >= 0x600) > count = 1; > > - priv->error = regmap_bulk_write(priv->regmap, reg, , count); > + priv->error = regmap_bulk_write(priv->regmap, reg, , count); > } > > static void tc358768_read(struct tc358768_priv *priv, u32 reg, u32 *val) > -- > 2.26.0 > > ___ > dri-devel mailing list > dri-devel@lists.freedesktop.org > https://lists.freedesktop.org/mailman/listinfo/dri-devel ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [PATCH] misc: sram: Add dma-heap-export reserved SRAM area type
On 4/24/20 8:44 PM, John Stultz wrote: > On Fri, Apr 24, 2020 at 3:27 PM Andrew F. Davis wrote: >> This new export type exposes to userspace the SRAM area as a DMA-Heap, >> this allows for allocations as DMA-BUFs that can be consumed by various >> DMA-BUF supporting devices. >> >> Signed-off-by: Andrew F. Davis > > Nice! Very excited to have the first new heap (that didn't come with > the initial patchset)! > > Overall looks good! I don't have any comment on the SRAM side of > things, but a few minor questions/nits below. > >> diff --git a/drivers/misc/sram-dma-heap.c b/drivers/misc/sram-dma-heap.c >> new file mode 100644 >> index ..38df0397f294 >> --- /dev/null >> +++ b/drivers/misc/sram-dma-heap.c >> @@ -0,0 +1,243 @@ >> +// SPDX-License-Identifier: GPL-2.0 >> +/* >> + * SRAM DMA-Heap userspace exporter >> + * >> + * Copyright (C) 2019 Texas Instruments Incorporated - http://www.ti.com/ >> + * Andrew F. Davis >> + */ >> + >> +#include >> +#include >> +#include >> +#include >> +#include >> +#include >> +#include >> +#include >> +#include >> + >> +#include "sram.h" >> + >> +struct sram_dma_heap { >> + struct dma_heap *heap; >> + struct gen_pool *pool; >> +}; >> + >> +struct sram_dma_heap_buffer { >> + struct gen_pool *pool; >> + struct list_head attachments; >> + struct mutex attachments_lock; >> + unsigned long len; >> + void *vaddr; >> + phys_addr_t paddr; >> +}; >> + >> +struct dma_heap_attachment { >> + struct device *dev; >> + struct sg_table *table; >> + struct list_head list; >> +}; >> + >> +static int dma_heap_attach(struct dma_buf *dmabuf, >> + struct dma_buf_attachment *attachment) >> +{ >> + struct sram_dma_heap_buffer *buffer = dmabuf->priv; >> + struct dma_heap_attachment *a; >> + struct sg_table *table; >> + >> + a = kzalloc(sizeof(*a), GFP_KERNEL); >> + if (!a) >> + return -ENOMEM; >> + >> + table = kmalloc(sizeof(*table), GFP_KERNEL); >> + if (!table) { >> + kfree(a); >> + return -ENOMEM; >> + } >> + if (sg_alloc_table(table, 1, GFP_KERNEL)) { >> + kfree(table); >> + kfree(a); >> + return -ENOMEM; >> + } >> + sg_set_page(table->sgl, pfn_to_page(PFN_DOWN(buffer->paddr)), >> buffer->len, 0); >> + >> + a->table = table; >> + a->dev = attachment->dev; >> + INIT_LIST_HEAD(>list); >> + >> + attachment->priv = a; >> + >> + mutex_lock(>attachments_lock); >> + list_add(>list, >attachments); >> + mutex_unlock(>attachments_lock); >> + >> + return 0; >> +} >> + >> +static void dma_heap_detatch(struct dma_buf *dmabuf, >> +struct dma_buf_attachment *attachment) >> +{ >> + struct sram_dma_heap_buffer *buffer = dmabuf->priv; >> + struct dma_heap_attachment *a = attachment->priv; >> + >> + mutex_lock(>attachments_lock); >> + list_del(>list); >> + mutex_unlock(>attachments_lock); >> + >> + sg_free_table(a->table); >> + kfree(a->table); >> + kfree(a); >> +} >> + >> +static struct sg_table *dma_heap_map_dma_buf(struct dma_buf_attachment >> *attachment, >> +enum dma_data_direction >> direction) >> +{ >> + struct dma_heap_attachment *a = attachment->priv; >> + struct sg_table *table = a->table; >> + >> + if (!dma_map_sg_attrs(attachment->dev, table->sgl, table->nents, >> + direction, DMA_ATTR_SKIP_CPU_SYNC)) > > Might be nice to have a comment as to why you're using SKIP_CPU_SYNC > and why it's safe. > Ack, should be simple enough to explain that SRAM is non-cached and so this sync is not needed (and may not work either given the SRAM region does not have valid page structures assdociated). >> + return ERR_PTR(-ENOMEM); >> + >> + return table; >> +} >> + >> +static void dma_heap_unmap_dma_buf(struct dma_buf_attachment *attachment, >> + struct sg_table *table, >> + enum dma_data_direction direction) >> +{ >> + dma_unmap_sg_attrs(attachment->dev, table->sgl, table->nents, >> + direction, DMA_ATTR_SKIP_CPU_SYNC); >> +} >> + >> +static void dma_heap_dma_buf_release(struct dma_buf *dmabuf) >> +{ >> + struct sram_dma_heap_buffer *buffer = dmabuf->priv; >> + >> + gen_pool_free(buffer->pool, (unsigned long)buffer->vaddr, >> buffer->len); >> + kfree(buffer); >> +} >> + >> +static int dma_heap_mmap(struct dma_buf *dmabuf, struct vm_area_struct *vma) >> +{ >> + struct sram_dma_heap_buffer *buffer = dmabuf->priv; >> + int ret; >> + >> + /* SRAM mappings are not cached */ >> + vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot); >> + >> + ret = vm_iomap_memory(vma,
Re: [PATCH] [v2] amdgpu: fix gcc-4.8 build warnings
On Wed, Apr 29, 2020 at 3:42 PM Kazlauskas, Nicholas wrote: > > On 2020-04-29 5:20 a.m., Arnd Bergmann wrote: > > Older compilers warn about initializers with incorrect curly > > braces: > > > > drivers/gpu/drm/drm_dp_mst_topology.c: In function > > 'drm_dp_mst_dsc_aux_for_port': > > drivers/gpu/drm/drm_dp_mst_topology.c:5497:9: error: missing braces around > > initializer [-Werror=missing-braces] > >struct drm_dp_desc desc = { 0 }; > > ^ > > > > Change all instances in the amd gpu driver to using the GNU empty > > initializer extension. > > These should actually be memset - instead of GCC complaining, it'll be > clang instead. I'm not sure what you mean, clang certainly supports most GNU extensions, and this one is used all over the kernel. There is a good reason for using memset instead of ={}, e.g. when you want to be sure that all padding fields get initialized before copying stack variables to user space, but I find it a little harder to read. Arnd ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH v6 09/16] drm/i915: Support DP MST in enc_to_dig_port() function
From: Sean Paul Although DP_MST fake encoders are not subclassed from digital ports, they are associated with them. Support these encoders. Signed-off-by: Sean Paul Link: https://patchwork.freedesktop.org/patch/msgid/20191203173638.94919-9-s...@poorly.run #v1 Link: https://patchwork.freedesktop.org/patch/msgid/20191212190230.188505-10-s...@poorly.run #v2 Link: https://patchwork.freedesktop.org/patch/msgid/20200117193103.156821-10-s...@poorly.run #v3 Link: https://patchwork.freedesktop.org/patch/msgid/20200218220242.107265-10-s...@poorly.run #v4 Link: https://patchwork.freedesktop.org/patch/msgid/20200305201236.152307-10-s...@poorly.run #v5 Changes in v2: -None Changes in v3: -None Changes in v4: -None Changes in v5: -None Changes in v6: -None --- .../drm/i915/display/intel_display_types.h| 21 --- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h index 69edfab4e266..f17911e25452 100644 --- a/drivers/gpu/drm/i915/display/intel_display_types.h +++ b/drivers/gpu/drm/i915/display/intel_display_types.h @@ -1525,6 +1525,18 @@ static inline bool intel_encoder_is_dig_port(struct intel_encoder *encoder) } } +static inline bool intel_encoder_is_mst(struct intel_encoder *encoder) +{ + return encoder->type == INTEL_OUTPUT_DP_MST; +} + +static inline struct intel_dp_mst_encoder * +enc_to_mst(struct intel_encoder *encoder) +{ + return container_of(>base, struct intel_dp_mst_encoder, + base.base); +} + static inline struct intel_digital_port * enc_to_dig_port(struct intel_encoder *encoder) { @@ -1533,6 +1545,8 @@ enc_to_dig_port(struct intel_encoder *encoder) if (intel_encoder_is_dig_port(intel_encoder)) return container_of(>base, struct intel_digital_port, base.base); + else if (intel_encoder_is_mst(intel_encoder)) + return enc_to_mst(encoder)->primary; else return NULL; } @@ -1543,13 +1557,6 @@ intel_attached_dig_port(struct intel_connector *connector) return enc_to_dig_port(intel_attached_encoder(connector)); } -static inline struct intel_dp_mst_encoder * -enc_to_mst(struct intel_encoder *encoder) -{ - return container_of(>base, struct intel_dp_mst_encoder, - base.base); -} - static inline struct intel_dp *enc_to_intel_dp(struct intel_encoder *encoder) { return _to_dig_port(encoder)->dp; -- Sean Paul, Software Engineer, Google / Chromium OS ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH v6 11/16] drm/i915: Factor out HDCP shim functions from dp for use by dp_mst
From: Sean Paul These functions are all the same for dp and dp_mst, so move them into a dedicated file for both sst and mst to use. Signed-off-by: Sean Paul Link: https://patchwork.freedesktop.org/patch/msgid/20191203173638.94919-11-s...@poorly.run #v1 Link: https://patchwork.freedesktop.org/patch/msgid/20191212190230.188505-12-s...@poorly.run #v2 Link: https://patchwork.freedesktop.org/patch/msgid/20200117193103.156821-12-s...@poorly.run #v3 Link: https://patchwork.freedesktop.org/patch/msgid/20200218220242.107265-12-s...@poorly.run #v4 Link: https://patchwork.freedesktop.org/patch/msgid/20200305201236.152307-12-s...@poorly.run #v5 Changes in v2: -None Changes in v3: -Created intel_dp_hdcp.c for the shared functions to live (Ville) Changes in v4: -Rebased on new drm logging change Changes in v5: -None Changes in v6: -None --- drivers/gpu/drm/i915/Makefile| 1 + drivers/gpu/drm/i915/display/intel_dp.c | 614 +- drivers/gpu/drm/i915/display/intel_dp.h | 3 + drivers/gpu/drm/i915/display/intel_dp_hdcp.c | 636 +++ 4 files changed, 644 insertions(+), 610 deletions(-) create mode 100644 drivers/gpu/drm/i915/display/intel_dp_hdcp.c diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile index 21bb2fb5a6b8..d6787e98611e 100644 --- a/drivers/gpu/drm/i915/Makefile +++ b/drivers/gpu/drm/i915/Makefile @@ -229,6 +229,7 @@ i915-y += \ display/intel_ddi.o \ display/intel_dp.o \ display/intel_dp_aux_backlight.o \ + display/intel_dp_hdcp.o \ display/intel_dp_link_training.o \ display/intel_dp_mst.o \ display/intel_dsi.o \ diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index a33ee8f30d14..5bcdf6f025eb 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -6551,609 +6551,6 @@ void intel_dp_encoder_suspend(struct intel_encoder *intel_encoder) edp_panel_vdd_off_sync(intel_dp); } -static void intel_dp_hdcp_wait_for_cp_irq(struct intel_hdcp *hdcp, int timeout) -{ - long ret; - -#define C (hdcp->cp_irq_count_cached != atomic_read(>cp_irq_count)) - ret = wait_event_interruptible_timeout(hdcp->cp_irq_queue, C, - msecs_to_jiffies(timeout)); - - if (!ret) - DRM_DEBUG_KMS("Timedout at waiting for CP_IRQ\n"); -} - -static -int intel_dp_hdcp_write_an_aksv(struct intel_digital_port *intel_dig_port, - u8 *an) -{ - struct drm_i915_private *i915 = to_i915(intel_dig_port->base.base.dev); - u8 aksv[DRM_HDCP_KSV_LEN] = {}; - ssize_t dpcd_ret; - - dpcd_ret = drm_dp_dpcd_write(_dig_port->dp.aux, DP_AUX_HDCP_AN, -an, DRM_HDCP_AN_LEN); - if (dpcd_ret != DRM_HDCP_AN_LEN) { - drm_dbg_kms(>drm, - "Failed to write An over DP/AUX (%zd)\n", - dpcd_ret); - return dpcd_ret >= 0 ? -EIO : dpcd_ret; - } - - /* -* Since Aksv is Oh-So-Secret, we can't access it in software. So we -* send an empty buffer of the correct length through the DP helpers. On -* the other side, in the transfer hook, we'll generate a flag based on -* the destination address which will tickle the hardware to output the -* Aksv on our behalf after the header is sent. -*/ - dpcd_ret = drm_dp_dpcd_write(_dig_port->dp.aux, DP_AUX_HDCP_AKSV, -aksv, DRM_HDCP_KSV_LEN); - if (dpcd_ret != DRM_HDCP_KSV_LEN) { - drm_dbg_kms(>drm, - "Failed to write Aksv over DP/AUX (%zd)\n", - dpcd_ret); - return dpcd_ret >= 0 ? -EIO : dpcd_ret; - } - return 0; -} - -static int intel_dp_hdcp_read_bksv(struct intel_digital_port *intel_dig_port, - u8 *bksv) -{ - struct drm_i915_private *i915 = to_i915(intel_dig_port->base.base.dev); - ssize_t ret; - - ret = drm_dp_dpcd_read(_dig_port->dp.aux, DP_AUX_HDCP_BKSV, bksv, - DRM_HDCP_KSV_LEN); - if (ret != DRM_HDCP_KSV_LEN) { - drm_dbg_kms(>drm, - "Read Bksv from DP/AUX failed (%zd)\n", ret); - return ret >= 0 ? -EIO : ret; - } - return 0; -} - -static int intel_dp_hdcp_read_bstatus(struct intel_digital_port *intel_dig_port, - u8 *bstatus) -{ - struct drm_i915_private *i915 = to_i915(intel_dig_port->base.base.dev); - ssize_t ret; - - /* -* For some reason the HDMI and DP HDCP specs call this register -* definition by different names. In the HDMI spec, it's called BSTATUS, -* but in DP it's called BINFO. -*/ - ret =
[PATCH v6 03/16] drm/i915: WARN if HDCP signalling is enabled upon disable
From: Sean Paul HDCP signalling should not be left on, WARN if it is Cc: Ville Syrjälä Cc: Daniel Vetter Reviewed-by: Ramalingam C Signed-off-by: Sean Paul Link: https://patchwork.freedesktop.org/patch/msgid/20191212190230.188505-4-s...@poorly.run #v2 Link: https://patchwork.freedesktop.org/patch/msgid/20200117193103.156821-4-s...@poorly.run #v3 Link: https://patchwork.freedesktop.org/patch/msgid/20200218220242.107265-4-s...@poorly.run #v4 Link: https://patchwork.freedesktop.org/patch/msgid/20200305201236.152307-4-s...@poorly.run #v5 Changes in v2: -Added to the set in lieu of just clearing the bit Changes in v3: -None Changes in v4: -None Changes in v5: -Change WARN_ON to drm_WARN_ON Changes in v6: -None --- drivers/gpu/drm/i915/display/intel_ddi.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c b/drivers/gpu/drm/i915/display/intel_ddi.c index 5601673c3f30..08844ba9dcb5 100644 --- a/drivers/gpu/drm/i915/display/intel_ddi.c +++ b/drivers/gpu/drm/i915/display/intel_ddi.c @@ -1663,6 +1663,8 @@ void intel_ddi_disable_transcoder_func(const struct intel_crtc_state *crtc_state ctl = intel_de_read(dev_priv, TRANS_DDI_FUNC_CTL(cpu_transcoder)); + drm_WARN_ON(crtc->base.dev, ctl & TRANS_DDI_HDCP_SIGNALLING); + ctl &= ~TRANS_DDI_FUNC_ENABLE; if (IS_GEN_RANGE(dev_priv, 8, 10)) -- Sean Paul, Software Engineer, Google / Chromium OS ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH v6 04/16] drm/i915: Intercept Aksv writes in the aux hooks
From: Sean Paul Instead of hand rolling the transfer ourselves in the hdcp hook, inspect aux messages and add the aksv flag in the aux transfer hook. IIRC, this was the original implementation and folks wanted this hack to be isolated to the hdcp code, which makes sense. However in testing an LG monitor on my desk, I noticed it was passing back a DEFER reply. This wasn't handled in our hand-rolled code and HDCP auth was failing as a result. Instead of copy/pasting all of the retry logic and delays from drm dp helpers, let's just use the helpers and hide the aksv select as best as we can. Reviewed-by: Ville Syrjälä Reviewed-by: Ramalingam C Signed-off-by: Sean Paul Link: https://patchwork.freedesktop.org/patch/msgid/20191203173638.94919-3-s...@poorly.run #v1 Link: https://patchwork.freedesktop.org/patch/msgid/20191212190230.188505-5-s...@poorly.run #v2 Link: https://patchwork.freedesktop.org/patch/msgid/20200117193103.156821-5-s...@poorly.run #v3 Link: https://patchwork.freedesktop.org/patch/msgid/20200218220242.107265-5-s...@poorly.run #v4 Link: https://patchwork.freedesktop.org/patch/msgid/20200305201236.152307-5-s...@poorly.run #v5 Changes in v2: -Remove 'generate' in intel_dp_aux_generate_xfer_flags, make arg const (Ville) -Bundle Aksv if statement together (Ville) -Rename 'txbuf' to 'aksv' (Ville) Changes in v3: -None Changes in v4: -None Changes in v5: -None Changes in v6: -None --- drivers/gpu/drm/i915/display/intel_dp.c | 63 - 1 file changed, 29 insertions(+), 34 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index 6952b0295096..f33b3e273e05 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -1550,12 +1550,27 @@ intel_dp_aux_header(u8 txbuf[HEADER_SIZE], txbuf[3] = msg->size - 1; } +static u32 intel_dp_aux_xfer_flags(const struct drm_dp_aux_msg *msg) +{ + /* +* If we're trying to send the HDCP Aksv, we need to set a the Aksv +* select bit to inform the hardware to send the Aksv after our header +* since we can't access that data from software. +*/ + if ((msg->request & ~DP_AUX_I2C_MOT) == DP_AUX_NATIVE_WRITE && + msg->address == DP_AUX_HDCP_AKSV) + return DP_AUX_CH_CTL_AUX_AKSV_SELECT; + + return 0; +} + static ssize_t intel_dp_aux_transfer(struct drm_dp_aux *aux, struct drm_dp_aux_msg *msg) { struct intel_dp *intel_dp = container_of(aux, struct intel_dp, aux); u8 txbuf[20], rxbuf[20]; size_t txsize, rxsize; + u32 flags = intel_dp_aux_xfer_flags(msg); int ret; intel_dp_aux_header(txbuf, msg); @@ -1576,7 +1591,7 @@ intel_dp_aux_transfer(struct drm_dp_aux *aux, struct drm_dp_aux_msg *msg) memcpy(txbuf + HEADER_SIZE, msg->buffer, msg->size); ret = intel_dp_aux_xfer(intel_dp, txbuf, txsize, - rxbuf, rxsize, 0); + rxbuf, rxsize, flags); if (ret > 0) { msg->reply = rxbuf[0] >> 4; @@ -1599,7 +1614,7 @@ intel_dp_aux_transfer(struct drm_dp_aux *aux, struct drm_dp_aux_msg *msg) return -E2BIG; ret = intel_dp_aux_xfer(intel_dp, txbuf, txsize, - rxbuf, rxsize, 0); + rxbuf, rxsize, flags); if (ret > 0) { msg->reply = rxbuf[0] >> 4; /* @@ -6553,17 +6568,9 @@ int intel_dp_hdcp_write_an_aksv(struct intel_digital_port *intel_dig_port, u8 *an) { struct drm_i915_private *i915 = to_i915(intel_dig_port->base.base.dev); - struct intel_dp *intel_dp = enc_to_intel_dp(to_intel_encoder(_dig_port->base.base)); - static const struct drm_dp_aux_msg msg = { - .request = DP_AUX_NATIVE_WRITE, - .address = DP_AUX_HDCP_AKSV, - .size = DRM_HDCP_KSV_LEN, - }; - u8 txbuf[HEADER_SIZE + DRM_HDCP_KSV_LEN] = {}, rxbuf[2], reply = 0; + u8 aksv[DRM_HDCP_KSV_LEN] = {}; ssize_t dpcd_ret; - int ret; - /* Output An first, that's easy */ dpcd_ret = drm_dp_dpcd_write(_dig_port->dp.aux, DP_AUX_HDCP_AN, an, DRM_HDCP_AN_LEN); if (dpcd_ret != DRM_HDCP_AN_LEN) { @@ -6574,31 +6581,19 @@ int intel_dp_hdcp_write_an_aksv(struct intel_digital_port *intel_dig_port, } /* -* Since Aksv is Oh-So-Secret, we can't access it in software. So in -* order to get it on the wire, we need to create the AUX header as if -* we were writing the data, and then tickle the hardware to output the -* data once the header is sent out. +* Since Aksv is Oh-So-Secret, we can't access it in software. So we +
[PATCH v6 16/16] drm/i915: Add HDCP 1.4 support for MST connectors
From: Sean Paul Now that all the groundwork has been laid, we can turn on HDCP 1.4 over MST. Everything except for toggling the HDCP signalling and HDCP 2.2 support is the same as the DP case, so we'll re-use those callbacks Cc: Juston Li Signed-off-by: Sean Paul Link: https://patchwork.freedesktop.org/patch/msgid/20191203173638.94919-12-s...@poorly.run #v1 Link: https://patchwork.freedesktop.org/patch/msgid/20191212190230.188505-13-s...@poorly.run #v2 Link: https://patchwork.freedesktop.org/patch/msgid/20200117193103.156821-13-s...@poorly.run #v3 Link: https://patchwork.freedesktop.org/patch/msgid/20200218220242.107265-15-s...@poorly.run #v4 Link: https://patchwork.freedesktop.org/patch/msgid/20200305201236.152307-17-s...@poorly.run #v5 Changes in v2: -Toggle HDCP from encoder disable/enable -Don't disable HDCP on MST connector destroy, leave that for encoder disable, just ensure the check_work routine isn't running any longer Changes in v3: -Place the shim in the new intel_dp_hdcp.c file (Ville) Changes in v4: -Actually use the mst shim for mst connections (Juston) -Use QUERY_STREAM_ENC_STATUS MST message to verify channel is encrypted Changes in v5: -Add sleep on disable signalling to match hdmi delay Changes in v6: -Disable HDCP over MST on GEN12+ since I'm unsure how it should work and I don't have hardware to test it --- drivers/gpu/drm/i915/display/intel_dp_hdcp.c | 107 ++- drivers/gpu/drm/i915/display/intel_dp_mst.c | 18 2 files changed, 124 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/display/intel_dp_hdcp.c b/drivers/gpu/drm/i915/display/intel_dp_hdcp.c index 4e3dafbea1f9..331fdb312e05 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_hdcp.c +++ b/drivers/gpu/drm/i915/display/intel_dp_hdcp.c @@ -7,10 +7,12 @@ */ #include +#include #include #include #include "intel_display_types.h" +#include "intel_ddi.h" #include "intel_dp.h" #include "intel_hdcp.h" @@ -618,6 +620,106 @@ static const struct intel_hdcp_shim intel_dp_hdcp_shim = { .protocol = HDCP_PROTOCOL_DP, }; +static int +intel_dp_mst_hdcp_toggle_signalling(struct intel_digital_port *intel_dig_port, + enum transcoder cpu_transcoder, + bool enable) +{ + struct drm_i915_private *i915 = to_i915(intel_dig_port->base.base.dev); + int ret; + + if (!enable) + usleep_range(6, 60); /* Bspec says >= 6us */ + + ret = intel_ddi_toggle_hdcp_signalling(_dig_port->base, + cpu_transcoder, enable); + if (ret) + drm_dbg_kms(>drm, "%s HDCP signalling failed (%d)\n", + enable ? "Enable" : "Disable", ret); + return ret; +} + +static +int intel_dp_mst_hdcp2_write_msg(struct intel_digital_port *intel_dig_port, +void *buf, size_t size) +{ + return -EOPNOTSUPP; +} + +static +int intel_dp_mst_hdcp2_read_msg(struct intel_digital_port *intel_dig_port, + u8 msg_id, void *buf, size_t size) +{ + return -EOPNOTSUPP; +} + +static int +intel_dp_mst_hdcp2_config_stream_type(struct intel_digital_port *intel_dig_port, + bool is_repeater, u8 content_type) +{ + return -EOPNOTSUPP; +} + +static +int intel_dp_mst_hdcp2_check_link(struct intel_digital_port *intel_dig_port) +{ + return -EOPNOTSUPP; +} + +static +int intel_dp_mst_hdcp2_capable(struct intel_digital_port *intel_dig_port, + bool *capable) +{ + *capable = false; + return 0; +} + +static +bool intel_dp_mst_hdcp_check_link(struct intel_digital_port *intel_dig_port, + struct intel_connector *connector) +{ + struct drm_i915_private *i915 = to_i915(intel_dig_port->base.base.dev); + struct intel_dp *intel_dp = _dig_port->dp; + struct drm_dp_query_stream_enc_status_ack_reply reply; + int ret; + + if (!intel_dp_hdcp_check_link(intel_dig_port, connector)) + return false; + + ret = drm_dp_send_query_stream_enc_status(_dp->mst_mgr, + connector->port, ); + if (ret) { + drm_dbg_kms(>drm, + "[CONNECTOR:%d:%s] failed QSES ret=%d\n", + connector->base.base.id, connector->base.name, ret); + return false; + } + + return reply.auth_completed && reply.encryption_enabled; +} + +static const struct intel_hdcp_shim intel_dp_mst_hdcp_shim = { + .write_an_aksv = intel_dp_hdcp_write_an_aksv, + .read_bksv = intel_dp_hdcp_read_bksv, + .read_bstatus = intel_dp_hdcp_read_bstatus, + .repeater_present = intel_dp_hdcp_repeater_present, + .read_ri_prime = intel_dp_hdcp_read_ri_prime, + .read_ksv_ready = intel_dp_hdcp_read_ksv_ready, +
[PATCH v6 06/16] drm/i915: Factor out hdcp->value assignments
From: Sean Paul This is a bit of housecleaning for a future patch. Instead of sprinkling hdcp->value assignments and prop_work scheduling everywhere, introduce a function to do it for us. Reviewed-by: Ramalingam C Signed-off-by: Sean Paul Link: https://patchwork.freedesktop.org/patch/msgid/20191203173638.94919-7-s...@poorly.run #v1 Link: https://patchwork.freedesktop.org/patch/msgid/20191212190230.188505-7-s...@poorly.run #v2 Link: https://patchwork.freedesktop.org/patch/msgid/20200117193103.156821-7-s...@poorly.run #v3 Link: https://patchwork.freedesktop.org/patch/msgid/20200218220242.107265-7-s...@poorly.run #v4 Link: https://patchwork.freedesktop.org/patch/msgid/20200305201236.152307-7-s...@poorly.run #v5 Changes in v2: -None Changes in v3: -None Changes in v4: -Rebased on top of drm_* logging changes Changes in v5: -Change WARN_ON to drm_WARN_ON Changes in v6: -None --- drivers/gpu/drm/i915/display/intel_hdcp.c | 67 --- 1 file changed, 46 insertions(+), 21 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_hdcp.c b/drivers/gpu/drm/i915/display/intel_hdcp.c index 41986a3e192c..ec02eaa43d39 100644 --- a/drivers/gpu/drm/i915/display/intel_hdcp.c +++ b/drivers/gpu/drm/i915/display/intel_hdcp.c @@ -877,6 +877,21 @@ static struct intel_connector *intel_hdcp_to_connector(struct intel_hdcp *hdcp) return container_of(hdcp, struct intel_connector, hdcp); } +static void intel_hdcp_update_value(struct intel_connector *connector, + u64 value, bool update_property) +{ + struct intel_hdcp *hdcp = >hdcp; + + drm_WARN_ON(connector->base.dev, !mutex_is_locked(>mutex)); + + if (hdcp->value == value) + return; + + hdcp->value = value; + if (update_property) + schedule_work(>prop_work); +} + /* Implements Part 3 of the HDCP authorization procedure */ static int intel_hdcp_check_link(struct intel_connector *connector) { @@ -904,15 +919,16 @@ static int intel_hdcp_check_link(struct intel_connector *connector) connector->base.name, connector->base.base.id, intel_de_read(dev_priv, HDCP_STATUS(dev_priv, cpu_transcoder, port))); ret = -ENXIO; - hdcp->value = DRM_MODE_CONTENT_PROTECTION_DESIRED; - schedule_work(>prop_work); + intel_hdcp_update_value(connector, + DRM_MODE_CONTENT_PROTECTION_DESIRED, + true); goto out; } if (hdcp->shim->check_link(intel_dig_port)) { if (hdcp->value != DRM_MODE_CONTENT_PROTECTION_UNDESIRED) { - hdcp->value = DRM_MODE_CONTENT_PROTECTION_ENABLED; - schedule_work(>prop_work); + intel_hdcp_update_value(connector, + DRM_MODE_CONTENT_PROTECTION_ENABLED, true); } goto out; } @@ -924,16 +940,18 @@ static int intel_hdcp_check_link(struct intel_connector *connector) ret = _intel_hdcp_disable(connector); if (ret) { drm_err(_priv->drm, "Failed to disable hdcp (%d)\n", ret); - hdcp->value = DRM_MODE_CONTENT_PROTECTION_DESIRED; - schedule_work(>prop_work); + intel_hdcp_update_value(connector, + DRM_MODE_CONTENT_PROTECTION_DESIRED, + true); goto out; } ret = _intel_hdcp_enable(connector); if (ret) { drm_err(_priv->drm, "Failed to enable hdcp (%d)\n", ret); - hdcp->value = DRM_MODE_CONTENT_PROTECTION_DESIRED; - schedule_work(>prop_work); + intel_hdcp_update_value(connector, + DRM_MODE_CONTENT_PROTECTION_DESIRED, + true); goto out; } @@ -1769,16 +1787,18 @@ static int intel_hdcp2_check_link(struct intel_connector *connector) "HDCP2.2 link stopped the encryption, %x\n", intel_de_read(dev_priv, HDCP2_STATUS(dev_priv, cpu_transcoder, port))); ret = -ENXIO; - hdcp->value = DRM_MODE_CONTENT_PROTECTION_DESIRED; - schedule_work(>prop_work); + intel_hdcp_update_value(connector, + DRM_MODE_CONTENT_PROTECTION_DESIRED, + true); goto out; } ret = hdcp->shim->check_2_2_link(intel_dig_port); if (ret == HDCP_LINK_PROTECTED) { if (hdcp->value != DRM_MODE_CONTENT_PROTECTION_UNDESIRED) { - hdcp->value = DRM_MODE_CONTENT_PROTECTION_ENABLED; - schedule_work(>prop_work); +
[PATCH v6 13/16] drm/i915: Add connector to hdcp_shim->check_link()
From: Sean Paul Currently we derive the connector from digital port in check_link(). For MST, this isn't sufficient since the digital port passed into the function can have multiple connectors downstream. This patch adds connector to the check_link() arguments so we have it when we need it. Signed-off-by: Sean Paul Link: https://patchwork.freedesktop.org/patch/msgid/20200218220242.107265-13-s...@poorly.run #v4 Link: https://patchwork.freedesktop.org/patch/msgid/20200305201236.152307-14-s...@poorly.run #v5 Changes in v4: -Added to the set Changes in v5: -None Changes in v6: -None --- drivers/gpu/drm/i915/display/intel_display_types.h | 3 ++- drivers/gpu/drm/i915/display/intel_dp_hdcp.c | 3 ++- drivers/gpu/drm/i915/display/intel_hdcp.c | 2 +- drivers/gpu/drm/i915/display/intel_hdmi.c | 5 ++--- 4 files changed, 7 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h index f17911e25452..8365f9d08e2c 100644 --- a/drivers/gpu/drm/i915/display/intel_display_types.h +++ b/drivers/gpu/drm/i915/display/intel_display_types.h @@ -318,7 +318,8 @@ struct intel_hdcp_shim { bool enable); /* Ensures the link is still protected */ - bool (*check_link)(struct intel_digital_port *intel_dig_port); + bool (*check_link)(struct intel_digital_port *intel_dig_port, + struct intel_connector *connector); /* Detects panel's hdcp capability. This is optional for HDMI. */ int (*hdcp_capable)(struct intel_digital_port *intel_dig_port, diff --git a/drivers/gpu/drm/i915/display/intel_dp_hdcp.c b/drivers/gpu/drm/i915/display/intel_dp_hdcp.c index 52207f767f48..4e3dafbea1f9 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_hdcp.c +++ b/drivers/gpu/drm/i915/display/intel_dp_hdcp.c @@ -565,7 +565,8 @@ int intel_dp_hdcp_toggle_signalling(struct intel_digital_port *intel_dig_port, } static -bool intel_dp_hdcp_check_link(struct intel_digital_port *intel_dig_port) +bool intel_dp_hdcp_check_link(struct intel_digital_port *intel_dig_port, + struct intel_connector *connector) { struct drm_i915_private *i915 = to_i915(intel_dig_port->base.base.dev); ssize_t ret; diff --git a/drivers/gpu/drm/i915/display/intel_hdcp.c b/drivers/gpu/drm/i915/display/intel_hdcp.c index 041fe1f69b73..9377919251bf 100644 --- a/drivers/gpu/drm/i915/display/intel_hdcp.c +++ b/drivers/gpu/drm/i915/display/intel_hdcp.c @@ -953,7 +953,7 @@ static int intel_hdcp_check_link(struct intel_connector *connector) goto out; } - if (hdcp->shim->check_link(intel_dig_port)) { + if (hdcp->shim->check_link(intel_dig_port, connector)) { if (hdcp->value != DRM_MODE_CONTENT_PROTECTION_UNDESIRED) { intel_hdcp_update_value(connector, DRM_MODE_CONTENT_PROTECTION_ENABLED, true); diff --git a/drivers/gpu/drm/i915/display/intel_hdmi.c b/drivers/gpu/drm/i915/display/intel_hdmi.c index 9c5b40e4c0c4..52166582a199 100644 --- a/drivers/gpu/drm/i915/display/intel_hdmi.c +++ b/drivers/gpu/drm/i915/display/intel_hdmi.c @@ -1546,11 +1546,10 @@ int intel_hdmi_hdcp_toggle_signalling(struct intel_digital_port *intel_dig_port, } static -bool intel_hdmi_hdcp_check_link(struct intel_digital_port *intel_dig_port) +bool intel_hdmi_hdcp_check_link(struct intel_digital_port *intel_dig_port, + struct intel_connector *connector) { struct drm_i915_private *i915 = to_i915(intel_dig_port->base.base.dev); - struct intel_connector *connector = - intel_dig_port->hdmi.attached_connector; enum port port = intel_dig_port->base.port; enum transcoder cpu_transcoder = connector->hdcp.cpu_transcoder; int ret; -- Sean Paul, Software Engineer, Google / Chromium OS ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH v6 14/16] drm/mst: Add support for QUERY_STREAM_ENCRYPTION_STATUS MST sideband message
From: Sean Paul Used to query whether an MST stream is encrypted or not. Signed-off-by: Sean Paul Link: https://patchwork.freedesktop.org/patch/msgid/20200218220242.107265-14-s...@poorly.run #v4 Link: https://patchwork.freedesktop.org/patch/msgid/20200305201236.152307-15-s...@poorly.run #v5 Changes in v4: -Added to the set Changes in v5: -None Changes in v6: -Use FIELD_PREP to generate request buffer bitfields (Lyude) -Add mst selftest and dump/decode_sideband_req for QSES (Lyude) --- drivers/gpu/drm/drm_dp_mst_topology.c | 142 ++ .../drm/selftests/test-drm_dp_mst_helper.c| 17 +++ include/drm/drm_dp_helper.h | 3 + include/drm/drm_dp_mst_helper.h | 44 ++ 4 files changed, 206 insertions(+) diff --git a/drivers/gpu/drm/drm_dp_mst_topology.c b/drivers/gpu/drm/drm_dp_mst_topology.c index 2d4132e0a98f..e516d0f098ea 100644 --- a/drivers/gpu/drm/drm_dp_mst_topology.c +++ b/drivers/gpu/drm/drm_dp_mst_topology.c @@ -20,11 +20,13 @@ * OF THIS SOFTWARE. */ +#include #include #include #include #include #include +#include #include #include #include @@ -419,6 +421,22 @@ drm_dp_encode_sideband_req(const struct drm_dp_sideband_msg_req_body *req, memcpy([idx], req->u.i2c_write.bytes, req->u.i2c_write.num_bytes); idx += req->u.i2c_write.num_bytes; break; + case DP_QUERY_STREAM_ENC_STATUS: { + const struct drm_dp_query_stream_enc_status *msg; + + msg = >u.enc_status; + buf[idx] = msg->stream_id; + idx++; + memcpy([idx], msg->client_id, sizeof(msg->client_id)); + idx += sizeof(msg->client_id); + buf[idx] = 0; + buf[idx] |= FIELD_PREP(GENMASK(1, 0), msg->stream_event); + buf[idx] |= msg->valid_stream_event ? BIT(2) : 0; + buf[idx] |= FIELD_PREP(GENMASK(4, 3), msg->stream_behavior); + buf[idx] |= msg->valid_stream_behavior ? BIT(5) : 0; + idx++; + } + break; } raw->cur_len = idx; } @@ -547,6 +565,20 @@ drm_dp_decode_sideband_req(const struct drm_dp_sideband_msg_tx *raw, return -ENOMEM; } break; + case DP_QUERY_STREAM_ENC_STATUS: + req->u.enc_status.stream_id = buf[idx++]; + for (i = 0; i < sizeof(req->u.enc_status.client_id); i++) + req->u.enc_status.client_id[i] = buf[idx++]; + + req->u.enc_status.stream_event = FIELD_GET(GENMASK(1, 0), + buf[idx]); + req->u.enc_status.valid_stream_event = FIELD_GET(BIT(2), +buf[idx]); + req->u.enc_status.stream_behavior = FIELD_GET(GENMASK(4, 3), + buf[idx]); + req->u.enc_status.valid_stream_behavior = FIELD_GET(BIT(5), + buf[idx]); + break; } return 0; @@ -625,6 +657,16 @@ drm_dp_dump_sideband_msg_req_body(const struct drm_dp_sideband_msg_req_body *req req->u.i2c_write.num_bytes, req->u.i2c_write.num_bytes, req->u.i2c_write.bytes); break; + case DP_QUERY_STREAM_ENC_STATUS: + P("stream_id=%u client_id=%*ph stream_event=%x " + "valid_event=%d stream_behavior=%x valid_behavior=%d", + req->u.enc_status.stream_id, + (int)ARRAY_SIZE(req->u.enc_status.client_id), + req->u.enc_status.client_id, req->u.enc_status.stream_event, + req->u.enc_status.valid_stream_event, + req->u.enc_status.stream_behavior, + req->u.enc_status.valid_stream_behavior); + break; default: P("???\n"); break; @@ -925,6 +967,34 @@ static bool drm_dp_sideband_parse_power_updown_phy_ack(struct drm_dp_sideband_ms return true; } +static bool +drm_dp_sideband_parse_query_stream_enc_status( + struct drm_dp_sideband_msg_rx *raw, + struct drm_dp_sideband_msg_reply_body *repmsg) +{ + struct drm_dp_query_stream_enc_status_ack_reply *reply; + + reply = >u.enc_status; + + reply->stream_id = raw->msg[3]; + + reply->reply_signed = raw->msg[2] & BIT(0); + + reply->hdcp_1x_device_present = raw->msg[2] & BIT(3); + reply->hdcp_2x_device_present = raw->msg[2] & BIT(4); + + reply->query_capable_device_present = raw->msg[2] & BIT(5); + reply->legacy_device_present = raw->msg[2] & BIT(6); + reply->unauthorizable_device_present = raw->msg[2] & BIT(7); + +
[PATCH v6 15/16] drm/i915: Print HDCP version info for all connectors
From: Sean Paul De-duplicate the HDCP version code for each connector and print it for all connectors. Cc: Juston Li Cc: Ramalingam C Reviewed-by: Juston Li Reviewed-by: Ramalingam C Signed-off-by: Sean Paul Link: https://patchwork.freedesktop.org/patch/msgid/20200227185714.171466-1-s...@poorly.run #v4 Link: https://patchwork.freedesktop.org/patch/msgid/20200305201236.152307-16-s...@poorly.run #v5 Changes in v4: - Added to the set Changes in v5: -Print "No connector support" for hdcp sink capability as well (Ram) Changes in v6: -None --- .../drm/i915/display/intel_display_debugfs.c | 21 --- 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display_debugfs.c b/drivers/gpu/drm/i915/display/intel_display_debugfs.c index 70525623bcdf..03c3208e4eb9 100644 --- a/drivers/gpu/drm/i915/display/intel_display_debugfs.c +++ b/drivers/gpu/drm/i915/display/intel_display_debugfs.c @@ -598,6 +598,11 @@ static void intel_hdcp_info(struct seq_file *m, { bool hdcp_cap, hdcp2_cap; + if (!intel_connector->hdcp.shim) { + seq_puts(m, "No Connector Support"); + goto out; + } + hdcp_cap = intel_hdcp_capable(intel_connector); hdcp2_cap = intel_hdcp2_capable(intel_connector); @@ -609,6 +614,7 @@ static void intel_hdcp_info(struct seq_file *m, if (!hdcp_cap && !hdcp2_cap) seq_puts(m, "None"); +out: seq_puts(m, "\n"); } @@ -625,10 +631,6 @@ static void intel_dp_info(struct seq_file *m, drm_dp_downstream_debug(m, intel_dp->dpcd, intel_dp->downstream_ports, _dp->aux); - if (intel_connector->hdcp.shim) { - seq_puts(m, "\tHDCP version: "); - intel_hdcp_info(m, intel_connector); - } } static void intel_dp_mst_info(struct seq_file *m, @@ -646,10 +648,6 @@ static void intel_hdmi_info(struct seq_file *m, struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(intel_encoder); seq_printf(m, "\taudio support: %s\n", yesno(intel_hdmi->has_audio)); - if (intel_connector->hdcp.shim) { - seq_puts(m, "\tHDCP version: "); - intel_hdcp_info(m, intel_connector); - } } static void intel_lvds_info(struct seq_file *m, @@ -705,6 +703,9 @@ static void intel_connector_info(struct seq_file *m, break; } + seq_puts(m, "\tHDCP version: "); + intel_hdcp_info(m, intel_connector); + seq_printf(m, "\tmodes:\n"); list_for_each_entry(mode, >modes, head) intel_seq_print_mode(m, 2, mode); @@ -2026,10 +2027,6 @@ static int i915_hdcp_sink_capability_show(struct seq_file *m, void *data) if (connector->status != connector_status_connected) return -ENODEV; - /* HDCP is supported by connector */ - if (!intel_connector->hdcp.shim) - return -EINVAL; - seq_printf(m, "%s:%d HDCP version: ", connector->name, connector->base.id); intel_hdcp_info(m, intel_connector); -- Sean Paul, Software Engineer, Google / Chromium OS ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH v6 08/16] drm/i915: Don't fully disable HDCP on a port if multiple pipes are using it
From: Sean Paul This patch is required for HDCP over MST. If a port is being used for multiple HDCP streams, we don't want to fully disable HDCP on a port if one of them is disabled. Instead, we just disable the HDCP signalling on that particular pipe and exit early. The last pipe to disable HDCP will also bring down HDCP on the port. In order to achieve this, we need to keep a refcount in intel_digital_port and protect it using a new hdcp_mutex. Cc: Ramalingam C Signed-off-by: Sean Paul Link: https://patchwork.freedesktop.org/patch/msgid/20191203173638.94919-8-s...@poorly.run #v1 Link: https://patchwork.freedesktop.org/patch/msgid/20191212190230.188505-9-s...@poorly.run #v2 Link: https://patchwork.freedesktop.org/patch/msgid/20200117193103.156821-9-s...@poorly.run #v3 Link: https://patchwork.freedesktop.org/patch/msgid/20200218220242.107265-9-s...@poorly.run #v4 Link: https://patchwork.freedesktop.org/patch/msgid/20200305201236.152307-9-s...@poorly.run #v5 Changes in v2: -Move the toggle_signalling call into _intel_hdcp_disable so it's called from check_work Changes in v3: -None Changes in v4: -None Changes in v5: -Change WARN_ON to drm_WARN_ON Changes in v6: -None --- drivers/gpu/drm/i915/display/intel_ddi.c | 3 ++ .../drm/i915/display/intel_display_types.h| 5 ++ drivers/gpu/drm/i915/display/intel_dp.c | 2 + drivers/gpu/drm/i915/display/intel_hdcp.c | 53 +++ drivers/gpu/drm/i915/display/intel_hdmi.c | 2 + 5 files changed, 56 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c b/drivers/gpu/drm/i915/display/intel_ddi.c index dc5d39ae4743..11155a8a73c0 100644 --- a/drivers/gpu/drm/i915/display/intel_ddi.c +++ b/drivers/gpu/drm/i915/display/intel_ddi.c @@ -4801,6 +4801,9 @@ void intel_ddi_init(struct drm_i915_private *dev_priv, enum port port) drm_encoder_init(_priv->drm, >base, _ddi_funcs, DRM_MODE_ENCODER_TMDS, "DDI %c", port_name(port)); + mutex_init(_dig_port->hdcp_mutex); + intel_dig_port->num_hdcp_streams = 0; + encoder->hotplug = intel_ddi_hotplug; encoder->compute_output_type = intel_ddi_compute_output_type; encoder->compute_config = intel_ddi_compute_config; diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h index 383046050c37..69edfab4e266 100644 --- a/drivers/gpu/drm/i915/display/intel_display_types.h +++ b/drivers/gpu/drm/i915/display/intel_display_types.h @@ -1411,6 +1411,11 @@ struct intel_digital_port { enum phy_fia tc_phy_fia; u8 tc_phy_fia_idx; + /* protects num_hdcp_streams reference count */ + struct mutex hdcp_mutex; + /* the number of pipes using HDCP signalling out of this port */ + unsigned int num_hdcp_streams; + void (*write_infoframe)(struct intel_encoder *encoder, const struct intel_crtc_state *crtc_state, unsigned int type, diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index 39c1304fe071..a33ee8f30d14 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -8450,6 +8450,8 @@ bool intel_dp_init(struct drm_i915_private *dev_priv, intel_encoder = _dig_port->base; encoder = _encoder->base; + mutex_init(_dig_port->hdcp_mutex); + if (drm_encoder_init(_priv->drm, _encoder->base, _dp_enc_funcs, DRM_MODE_ENCODER_TMDS, "DP %c", port_name(port))) diff --git a/drivers/gpu/drm/i915/display/intel_hdcp.c b/drivers/gpu/drm/i915/display/intel_hdcp.c index a4446d47ef27..0c00bbc3f66e 100644 --- a/drivers/gpu/drm/i915/display/intel_hdcp.c +++ b/drivers/gpu/drm/i915/display/intel_hdcp.c @@ -801,6 +801,19 @@ static int _intel_hdcp_disable(struct intel_connector *connector) drm_dbg_kms(_priv->drm, "[%s:%d] HDCP is being disabled...\n", connector->base.name, connector->base.base.id); + /* +* If there are other connectors on this port using HDCP, don't disable +* it. Instead, toggle the HDCP signalling off on that particular +* connector/pipe and exit. +*/ + if (intel_dig_port->num_hdcp_streams > 0) { + ret = hdcp->shim->toggle_signalling(intel_dig_port, + cpu_transcoder, false); + if (ret) + DRM_ERROR("Failed to disable HDCP signalling\n"); + return ret; + } + hdcp->hdcp_encrypted = false; intel_de_write(dev_priv, HDCP_CONF(dev_priv, cpu_transcoder, port), 0); if (intel_de_wait_for_clear(dev_priv, @@ -880,6 +893,8 @@ static struct intel_connector *intel_hdcp_to_connector(struct intel_hdcp *hdcp) static void intel_hdcp_update_value(struct intel_connector
[PATCH v6 10/16] drm/i915: Use ddi_update_pipe in intel_dp_mst
From: Sean Paul In order to act upon content_protection property changes, we'll need to implement the .update_pipe() hook. We can re-use intel_ddi_update_pipe for this Signed-off-by: Sean Paul Link: https://patchwork.freedesktop.org/patch/msgid/20191203173638.94919-10-s...@poorly.run #v1 Link: https://patchwork.freedesktop.org/patch/msgid/20191212190230.188505-11-s...@poorly.run #v2 Link: https://patchwork.freedesktop.org/patch/msgid/20200117193103.156821-11-s...@poorly.run #v3 Link: https://patchwork.freedesktop.org/patch/msgid/20200218220242.107265-11-s...@poorly.run #v4 Link: https://patchwork.freedesktop.org/patch/msgid/20200305201236.152307-11-s...@poorly.run #v5 Changes in v2: -None Changes in v3: -None Changes in v4: -None Changes in v5: -None Changes in v6: -None --- drivers/gpu/drm/i915/display/intel_ddi.c| 11 ++- drivers/gpu/drm/i915/display/intel_dp.h | 6 ++ drivers/gpu/drm/i915/display/intel_dp_mst.c | 1 + 3 files changed, 13 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c b/drivers/gpu/drm/i915/display/intel_ddi.c index 11155a8a73c0..85dcb2dc2d3c 100644 --- a/drivers/gpu/drm/i915/display/intel_ddi.c +++ b/drivers/gpu/drm/i915/display/intel_ddi.c @@ -3865,13 +3865,14 @@ static void intel_ddi_update_pipe_dp(struct intel_atomic_state *state, intel_panel_update_backlight(state, encoder, crtc_state, conn_state); } -static void intel_ddi_update_pipe(struct intel_atomic_state *state, - struct intel_encoder *encoder, - const struct intel_crtc_state *crtc_state, - const struct drm_connector_state *conn_state) +void intel_ddi_update_pipe(struct intel_atomic_state *state, + struct intel_encoder *encoder, + const struct intel_crtc_state *crtc_state, + const struct drm_connector_state *conn_state) { - if (!intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI)) + if (!intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI) && + !intel_encoder_is_mst(encoder)) intel_ddi_update_pipe_dp(state, encoder, crtc_state, conn_state); diff --git a/drivers/gpu/drm/i915/display/intel_dp.h b/drivers/gpu/drm/i915/display/intel_dp.h index 6659ce15a693..0bd440382281 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.h +++ b/drivers/gpu/drm/i915/display/intel_dp.h @@ -16,6 +16,7 @@ struct drm_connector_state; struct drm_encoder; struct drm_i915_private; struct drm_modeset_acquire_ctx; +struct intel_atomic_state; struct intel_connector; struct intel_crtc_state; struct intel_digital_port; @@ -127,4 +128,9 @@ static inline unsigned int intel_dp_unused_lane_mask(int lane_count) u32 intel_dp_mode_to_fec_clock(u32 mode_clock); +void intel_ddi_update_pipe(struct intel_atomic_state *state, + struct intel_encoder *encoder, + const struct intel_crtc_state *crtc_state, + const struct drm_connector_state *conn_state); + #endif /* __INTEL_DP_H__ */ diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c b/drivers/gpu/drm/i915/display/intel_dp_mst.c index 4d2384650383..d9dc4dc6ea92 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_mst.c +++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c @@ -805,6 +805,7 @@ intel_dp_create_fake_mst_encoder(struct intel_digital_port *intel_dig_port, enum intel_encoder->compute_config_late = intel_dp_mst_compute_config_late; intel_encoder->disable = intel_mst_disable_dp; intel_encoder->post_disable = intel_mst_post_disable_dp; + intel_encoder->update_pipe = intel_ddi_update_pipe; intel_encoder->pre_pll_enable = intel_mst_pre_pll_enable_dp; intel_encoder->pre_enable = intel_mst_pre_enable_dp; intel_encoder->enable = intel_mst_enable_dp; -- Sean Paul, Software Engineer, Google / Chromium OS ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH v6 07/16] drm/i915: Protect workers against disappearing connectors
From: Sean Paul This patch adds some protection against connectors being destroyed before the HDCP workers are finished. For check_work, we do a synchronous cancel after the connector is unregistered which will ensure that it is finished before destruction. In the case of prop_work, we can't do a synchronous wait since it needs to take connection_mutex which could cause deadlock. Instead, we'll take a reference on the connector when scheduling prop_work and give it up once we're done. Reviewed-by: Ramalingam C Signed-off-by: Sean Paul Link: https://patchwork.freedesktop.org/patch/msgid/20191212190230.188505-8-s...@poorly.run #v2 Link: https://patchwork.freedesktop.org/patch/msgid/20200117193103.156821-8-s...@poorly.run #v3 Link: https://patchwork.freedesktop.org/patch/msgid/20200218220242.107265-8-s...@poorly.run #v4 Link: https://patchwork.freedesktop.org/patch/msgid/20200305201236.152307-8-s...@poorly.run #v5 Changes in v2: -Added to the set Changes in v3: -Change the WARN_ON condition in intel_hdcp_cleanup to allow for initializing connectors as well Changes in v4: -None Changes in v5: -Change WARN_ON to drm_WARN_ON Changes in v6: -None --- drivers/gpu/drm/i915/display/intel_hdcp.c | 44 --- 1 file changed, 39 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_hdcp.c b/drivers/gpu/drm/i915/display/intel_hdcp.c index ec02eaa43d39..a4446d47ef27 100644 --- a/drivers/gpu/drm/i915/display/intel_hdcp.c +++ b/drivers/gpu/drm/i915/display/intel_hdcp.c @@ -888,8 +888,10 @@ static void intel_hdcp_update_value(struct intel_connector *connector, return; hdcp->value = value; - if (update_property) + if (update_property) { + drm_connector_get(>base); schedule_work(>prop_work); + } } /* Implements Part 3 of the HDCP authorization procedure */ @@ -981,6 +983,8 @@ static void intel_hdcp_prop_work(struct work_struct *work) mutex_unlock(>mutex); drm_modeset_unlock(_priv->drm.mode_config.connection_mutex); + + drm_connector_put(>base); } bool is_hdcp_supported(struct drm_i915_private *dev_priv, enum port port) @@ -1860,6 +1864,9 @@ static void intel_hdcp_check_work(struct work_struct *work) check_work); struct intel_connector *connector = intel_hdcp_to_connector(hdcp); + if (drm_connector_is_unregistered(>base)) + return; + if (!intel_hdcp2_check_link(connector)) schedule_delayed_work(>check_work, DRM_HDCP2_CHECK_PERIOD_MS); @@ -2175,12 +2182,39 @@ void intel_hdcp_component_fini(struct drm_i915_private *dev_priv) void intel_hdcp_cleanup(struct intel_connector *connector) { - if (!connector->hdcp.shim) + struct intel_hdcp *hdcp = >hdcp; + + if (!hdcp->shim) return; - mutex_lock(>hdcp.mutex); - kfree(connector->hdcp.port_data.streams); - mutex_unlock(>hdcp.mutex); + /* +* If the connector is registered, it's possible userspace could kick +* off another HDCP enable, which would re-spawn the workers. +*/ + drm_WARN_ON(connector->base.dev, + connector->base.registration_state == DRM_CONNECTOR_REGISTERED); + + /* +* Now that the connector is not registered, check_work won't be run, +* but cancel any outstanding instances of it +*/ + cancel_delayed_work_sync(>check_work); + + /* +* We don't cancel prop_work in the same way as check_work since it +* requires connection_mutex which could be held while calling this +* function. Instead, we rely on the connector references grabbed before +* scheduling prop_work to ensure the connector is alive when prop_work +* is run. So if we're in the destroy path (which is where this +* function should be called), we're "guaranteed" that prop_work is not +* active (tl;dr This Should Never Happen). +*/ + drm_WARN_ON(connector->base.dev, work_pending(>prop_work)); + + mutex_lock(>mutex); + kfree(hdcp->port_data.streams); + hdcp->shim = NULL; + mutex_unlock(>mutex); } void intel_hdcp_atomic_check(struct drm_connector *connector, -- Sean Paul, Software Engineer, Google / Chromium OS ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH v6 12/16] drm/i915: Plumb port through hdcp init
From: Sean Paul This patch plumbs port through hdcp init instead of relying on intel_attached_encoder() to return a non-NULL encoder which won't work for MST connectors. Cc: Ville Syrjälä Signed-off-by: Sean Paul Changes in v5: -Added to the set Changes in v6: -None Signed-off-by: Sean Paul Link: https://patchwork.freedesktop.org/patch/msgid/20200305201236.152307-13-s...@poorly.run #v5 --- drivers/gpu/drm/i915/display/intel_dp_hdcp.c | 3 ++- drivers/gpu/drm/i915/display/intel_hdcp.c| 11 ++- drivers/gpu/drm/i915/display/intel_hdcp.h| 2 +- drivers/gpu/drm/i915/display/intel_hdmi.c| 2 +- 4 files changed, 10 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_dp_hdcp.c b/drivers/gpu/drm/i915/display/intel_dp_hdcp.c index 2c94dfbfe4cb..52207f767f48 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_hdcp.c +++ b/drivers/gpu/drm/i915/display/intel_dp_hdcp.c @@ -630,7 +630,8 @@ int intel_dp_init_hdcp(struct intel_digital_port *intel_dig_port, return 0; if (!intel_dp_is_edp(intel_dp)) - return intel_hdcp_init(intel_connector, _dp_hdcp_shim); + return intel_hdcp_init(intel_connector, port, + _dp_hdcp_shim); return 0; } diff --git a/drivers/gpu/drm/i915/display/intel_hdcp.c b/drivers/gpu/drm/i915/display/intel_hdcp.c index 0c00bbc3f66e..041fe1f69b73 100644 --- a/drivers/gpu/drm/i915/display/intel_hdcp.c +++ b/drivers/gpu/drm/i915/display/intel_hdcp.c @@ -1955,6 +1955,7 @@ static enum mei_fw_tc intel_get_mei_fw_tc(enum transcoder cpu_transcoder) } static int initialize_hdcp_port_data(struct intel_connector *connector, +enum port port, const struct intel_hdcp_shim *shim) { struct drm_i915_private *dev_priv = to_i915(connector->base.dev); @@ -1962,8 +1963,7 @@ static int initialize_hdcp_port_data(struct intel_connector *connector, struct hdcp_port_data *data = >port_data; if (INTEL_GEN(dev_priv) < 12) - data->fw_ddi = - intel_get_mei_fw_ddi_index(intel_attached_encoder(connector)->port); + data->fw_ddi = intel_get_mei_fw_ddi_index(port); else /* * As per ME FW API expectation, for GEN 12+, fw_ddi is filled @@ -2030,14 +2030,14 @@ void intel_hdcp_component_init(struct drm_i915_private *dev_priv) } } -static void intel_hdcp2_init(struct intel_connector *connector, +static void intel_hdcp2_init(struct intel_connector *connector, enum port port, const struct intel_hdcp_shim *shim) { struct drm_i915_private *i915 = to_i915(connector->base.dev); struct intel_hdcp *hdcp = >hdcp; int ret; - ret = initialize_hdcp_port_data(connector, shim); + ret = initialize_hdcp_port_data(connector, port, shim); if (ret) { drm_dbg_kms(>drm, "Mei hdcp data init failed\n"); return; @@ -2047,6 +2047,7 @@ static void intel_hdcp2_init(struct intel_connector *connector, } int intel_hdcp_init(struct intel_connector *connector, + enum port port, const struct intel_hdcp_shim *shim) { struct drm_i915_private *dev_priv = to_i915(connector->base.dev); @@ -2057,7 +2058,7 @@ int intel_hdcp_init(struct intel_connector *connector, return -EINVAL; if (is_hdcp2_supported(dev_priv)) - intel_hdcp2_init(connector, shim); + intel_hdcp2_init(connector, port, shim); ret = drm_connector_attach_content_protection_property(>base, diff --git a/drivers/gpu/drm/i915/display/intel_hdcp.h b/drivers/gpu/drm/i915/display/intel_hdcp.h index 86bbaec120cc..1bbf5b67ed0a 100644 --- a/drivers/gpu/drm/i915/display/intel_hdcp.h +++ b/drivers/gpu/drm/i915/display/intel_hdcp.h @@ -22,7 +22,7 @@ enum transcoder; void intel_hdcp_atomic_check(struct drm_connector *connector, struct drm_connector_state *old_state, struct drm_connector_state *new_state); -int intel_hdcp_init(struct intel_connector *connector, +int intel_hdcp_init(struct intel_connector *connector, enum port port, const struct intel_hdcp_shim *hdcp_shim); int intel_hdcp_enable(struct intel_connector *connector, enum transcoder cpu_transcoder, u8 content_type); diff --git a/drivers/gpu/drm/i915/display/intel_hdmi.c b/drivers/gpu/drm/i915/display/intel_hdmi.c index 93cd8a2a4be1..9c5b40e4c0c4 100644 --- a/drivers/gpu/drm/i915/display/intel_hdmi.c +++ b/drivers/gpu/drm/i915/display/intel_hdmi.c @@ -3240,7 +3240,7 @@ void intel_hdmi_init_connector(struct intel_digital_port *intel_dig_port, intel_hdmi->attached_connector = intel_connector; if (is_hdcp_supported(dev_priv, port)) { - int ret =
[PATCH v6 05/16] drm/i915: Use the cpu_transcoder in intel_hdcp to toggle HDCP signalling
From: Sean Paul Instead of using intel_dig_port's encoder pipe to determine which transcoder to toggle signalling on, use the cpu_transcoder field already stored in intel_hdmi. This is particularly important for MST. Suggested-by: Ville Syrjälä Reviewed-by: Ramalingam C Signed-off-by: Sean Paul Link: https://patchwork.freedesktop.org/patch/msgid/20191212190230.188505-6-s...@poorly.run #v2 Link: https://patchwork.freedesktop.org/patch/msgid/20200117193103.156821-6-s...@poorly.run #v3 Link: https://patchwork.freedesktop.org/patch/msgid/20200218220242.107265-6-s...@poorly.run #v4 Link: https://patchwork.freedesktop.org/patch/msgid/20200305201236.152307-6-s...@poorly.run #v5 Changes in v2: -Added to the set Changes in v3: -s/hdcp/hdmi/ in commit msg (Ram) Changes in v4: -Rebased on intel_de_(read|write) change Changes in v5: -Update hdcp->cpu_transcoder in intel_hdcp_enable so it works with pipe != 0 Changes in v6: -None --- drivers/gpu/drm/i915/display/intel_ddi.c | 13 +++-- drivers/gpu/drm/i915/display/intel_ddi.h | 2 ++ .../gpu/drm/i915/display/intel_display_types.h | 1 + drivers/gpu/drm/i915/display/intel_dp.c | 1 + drivers/gpu/drm/i915/display/intel_hdcp.c| 16 +--- drivers/gpu/drm/i915/display/intel_hdmi.c| 16 +++- 6 files changed, 27 insertions(+), 22 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c b/drivers/gpu/drm/i915/display/intel_ddi.c index 08844ba9dcb5..dc5d39ae4743 100644 --- a/drivers/gpu/drm/i915/display/intel_ddi.c +++ b/drivers/gpu/drm/i915/display/intel_ddi.c @@ -1692,12 +1692,12 @@ void intel_ddi_disable_transcoder_func(const struct intel_crtc_state *crtc_state } int intel_ddi_toggle_hdcp_signalling(struct intel_encoder *intel_encoder, +enum transcoder cpu_transcoder, bool enable) { struct drm_device *dev = intel_encoder->base.dev; struct drm_i915_private *dev_priv = to_i915(dev); intel_wakeref_t wakeref; - enum pipe pipe = 0; int ret = 0; u32 tmp; @@ -1706,19 +1706,12 @@ int intel_ddi_toggle_hdcp_signalling(struct intel_encoder *intel_encoder, if (drm_WARN_ON(dev, !wakeref)) return -ENXIO; - if (drm_WARN_ON(dev, - !intel_encoder->get_hw_state(intel_encoder, ))) { - ret = -EIO; - goto out; - } - - tmp = intel_de_read(dev_priv, TRANS_DDI_FUNC_CTL(pipe)); + tmp = intel_de_read(dev_priv, TRANS_DDI_FUNC_CTL(cpu_transcoder)); if (enable) tmp |= TRANS_DDI_HDCP_SIGNALLING; else tmp &= ~TRANS_DDI_HDCP_SIGNALLING; - intel_de_write(dev_priv, TRANS_DDI_FUNC_CTL(pipe), tmp); -out: + intel_de_write(dev_priv, TRANS_DDI_FUNC_CTL(cpu_transcoder), tmp); intel_display_power_put(dev_priv, intel_encoder->power_domain, wakeref); return ret; } diff --git a/drivers/gpu/drm/i915/display/intel_ddi.h b/drivers/gpu/drm/i915/display/intel_ddi.h index fbdf8ddde486..fc2e6889be11 100644 --- a/drivers/gpu/drm/i915/display/intel_ddi.h +++ b/drivers/gpu/drm/i915/display/intel_ddi.h @@ -16,6 +16,7 @@ struct intel_crtc_state; struct intel_dp; struct intel_dpll_hw_state; struct intel_encoder; +enum transcoder; void intel_ddi_fdi_post_disable(struct intel_atomic_state *state, struct intel_encoder *intel_encoder, @@ -46,6 +47,7 @@ u8 intel_ddi_dp_voltage_max(struct intel_encoder *encoder); u8 intel_ddi_dp_pre_emphasis_max(struct intel_encoder *encoder, u8 voltage_swing); int intel_ddi_toggle_hdcp_signalling(struct intel_encoder *intel_encoder, +enum transcoder cpu_transcoder, bool enable); void icl_sanitize_encoder_pll_mapping(struct intel_encoder *encoder); diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h index 9488449e4b94..383046050c37 100644 --- a/drivers/gpu/drm/i915/display/intel_display_types.h +++ b/drivers/gpu/drm/i915/display/intel_display_types.h @@ -314,6 +314,7 @@ struct intel_hdcp_shim { /* Enables HDCP signalling on the port */ int (*toggle_signalling)(struct intel_digital_port *intel_dig_port, +enum transcoder cpu_transcoder, bool enable); /* Ensures the link is still protected */ diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index f33b3e273e05..39c1304fe071 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -6752,6 +6752,7 @@ int intel_dp_hdcp_read_v_prime_part(struct intel_digital_port *intel_dig_port, static int intel_dp_hdcp_toggle_signalling(struct intel_digital_port
[PATCH v6 01/16] drm/i915: Fix sha_text population code
From: Sean Paul This patch fixes a few bugs: 1- We weren't taking into account sha_leftovers when adding multiple ksvs to sha_text. As such, we were or'ing the end of ksv[j - 1] with the beginning of ksv[j] 2- In the sha_leftovers == 2 and sha_leftovers == 3 case, bstatus was being placed on the wrong half of sha_text, overlapping the leftover ksv value 3- In the sha_leftovers == 2 case, we need to manually terminate the byte stream with 0x80 since the hardware doesn't have enough room to add it after writing M0 The upside is that all of the HDCP supported HDMI repeaters I could find on Amazon just strip HDCP anyways, so it turns out to be _really_ hard to hit any of these cases without an MST hub, which is not (yet) supported. Oh, and the sha_leftovers == 1 case works perfectly! Fixes: ee5e5e7a5e0f (drm/i915: Add HDCP framework + base implementation) Cc: Chris Wilson Cc: Ramalingam C Cc: Daniel Vetter Cc: Sean Paul Cc: Jani Nikula Cc: Joonas Lahtinen Cc: Rodrigo Vivi Cc: intel-...@lists.freedesktop.org Cc: # v4.17+ Reviewed-by: Ramalingam C Signed-off-by: Sean Paul Link: https://patchwork.freedesktop.org/patch/msgid/20191203173638.94919-2-s...@poorly.run #v1 Link: https://patchwork.freedesktop.org/patch/msgid/20191212190230.188505-2-s...@poorly.run #v2 Link: https://patchwork.freedesktop.org/patch/msgid/20200117193103.156821-2-s...@poorly.run #v3 Link: https://patchwork.freedesktop.org/patch/msgid/20200218220242.107265-2-s...@poorly.run #v4 Link: https://patchwork.freedesktop.org/patch/msgid/20200305201236.152307-2-s...@poorly.run #v5 Changes in v2: -None Changes in v3: -None Changes in v4: -Rebased on intel_de_write changes Changes in v5: -None Changes in v6: -None --- drivers/gpu/drm/i915/display/intel_hdcp.c | 26 +-- include/drm/drm_hdcp.h| 3 +++ 2 files changed, 23 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_hdcp.c b/drivers/gpu/drm/i915/display/intel_hdcp.c index 2cbc4619b4ce..525658fd201f 100644 --- a/drivers/gpu/drm/i915/display/intel_hdcp.c +++ b/drivers/gpu/drm/i915/display/intel_hdcp.c @@ -336,8 +336,10 @@ int intel_hdcp_validate_v_prime(struct intel_connector *connector, /* Fill up the empty slots in sha_text and write it out */ sha_empty = sizeof(sha_text) - sha_leftovers; - for (j = 0; j < sha_empty; j++) - sha_text |= ksv[j] << ((sizeof(sha_text) - j - 1) * 8); + for (j = 0; j < sha_empty; j++) { + u8 off = ((sizeof(sha_text) - j - 1 - sha_leftovers) * 8); + sha_text |= ksv[j] << off; + } ret = intel_write_sha_text(dev_priv, sha_text); if (ret < 0) @@ -435,7 +437,7 @@ int intel_hdcp_validate_v_prime(struct intel_connector *connector, /* Write 32 bits of text */ intel_de_write(dev_priv, HDCP_REP_CTL, rep_ctl | HDCP_SHA1_TEXT_32); - sha_text |= bstatus[0] << 24 | bstatus[1] << 16; + sha_text |= bstatus[0] << 8 | bstatus[1]; ret = intel_write_sha_text(dev_priv, sha_text); if (ret < 0) return ret; @@ -450,17 +452,29 @@ int intel_hdcp_validate_v_prime(struct intel_connector *connector, return ret; sha_idx += sizeof(sha_text); } + + /* +* Terminate the SHA-1 stream by hand. For the other leftover +* cases this is appended by the hardware. +*/ + intel_de_write(dev_priv, HDCP_REP_CTL, + rep_ctl | HDCP_SHA1_TEXT_32); + sha_text = DRM_HDCP_SHA1_TERMINATOR << 24; + ret = intel_write_sha_text(dev_priv, sha_text); + if (ret < 0) + return ret; + sha_idx += sizeof(sha_text); } else if (sha_leftovers == 3) { - /* Write 32 bits of text */ + /* Write 32 bits of text (filled from LSB) */ intel_de_write(dev_priv, HDCP_REP_CTL, rep_ctl | HDCP_SHA1_TEXT_32); - sha_text |= bstatus[0] << 24; + sha_text |= bstatus[0]; ret = intel_write_sha_text(dev_priv, sha_text); if (ret < 0) return ret; sha_idx += sizeof(sha_text); - /* Write 8 bits of text, 24 bits of M0 */ + /* Write 8 bits of text (filled from LSB), 24 bits of M0 */ intel_de_write(dev_priv, HDCP_REP_CTL, rep_ctl | HDCP_SHA1_TEXT_8); ret = intel_write_sha_text(dev_priv, bstatus[1]); diff --git a/include/drm/drm_hdcp.h b/include/drm/drm_hdcp.h index c6bab4986a65..fe58dbb46962 100644 ---
[PATCH v6 02/16] drm/i915: Clear the repeater bit on HDCP disable
From: Sean Paul On HDCP disable, clear the repeater bit. This ensures if we connect a non-repeater sink after a repeater, the bit is in the state we expect. Fixes: ee5e5e7a5e0f (drm/i915: Add HDCP framework + base implementation) Cc: Chris Wilson Cc: Ramalingam C Cc: Daniel Vetter Cc: Sean Paul Cc: Jani Nikula Cc: Joonas Lahtinen Cc: Rodrigo Vivi Cc: intel-...@lists.freedesktop.org Cc: # v4.17+ Reviewed-by: Ramalingam C Signed-off-by: Sean Paul Link: https://patchwork.freedesktop.org/patch/msgid/20191212190230.188505-3-s...@poorly.run #v2 Link: https://patchwork.freedesktop.org/patch/msgid/20200117193103.156821-3-s...@poorly.run #v3 Link: https://patchwork.freedesktop.org/patch/msgid/20200218220242.107265-3-s...@poorly.run #v4 Link: https://patchwork.freedesktop.org/patch/msgid/20200305201236.152307-3-s...@poorly.run #v5 Changes in v2: -Added to the set Changes in v3: -None I had previously agreed that clearing the rep_ctl bits on enable would also be a good idea. However when I committed that idea to code, it didn't look right. So let's rely on enables and disables being paired and everything outside of that will be considered a bug Changes in v4: -s/I915_(READ|WRITE)/intel_de_(read|write)/ Changes in v5: -None Changes in v6: -None --- drivers/gpu/drm/i915/display/intel_hdcp.c | 6 ++ 1 file changed, 6 insertions(+) diff --git a/drivers/gpu/drm/i915/display/intel_hdcp.c b/drivers/gpu/drm/i915/display/intel_hdcp.c index 525658fd201f..20175a53643d 100644 --- a/drivers/gpu/drm/i915/display/intel_hdcp.c +++ b/drivers/gpu/drm/i915/display/intel_hdcp.c @@ -795,6 +795,7 @@ static int _intel_hdcp_disable(struct intel_connector *connector) struct intel_hdcp *hdcp = >hdcp; enum port port = intel_dig_port->base.port; enum transcoder cpu_transcoder = hdcp->cpu_transcoder; + u32 repeater_ctl; int ret; drm_dbg_kms(_priv->drm, "[%s:%d] HDCP is being disabled...\n", @@ -810,6 +811,11 @@ static int _intel_hdcp_disable(struct intel_connector *connector) return -ETIMEDOUT; } + repeater_ctl = intel_hdcp_get_repeater_ctl(dev_priv, cpu_transcoder, + port); + intel_de_write(dev_priv, HDCP_REP_CTL, + intel_de_read(dev_priv, HDCP_REP_CTL) & ~repeater_ctl); + ret = hdcp->shim->toggle_signalling(intel_dig_port, false); if (ret) { drm_err(_priv->drm, "Failed to disable HDCP signalling\n"); -- Sean Paul, Software Engineer, Google / Chromium OS ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH v6 00/16] drm/i915: Add support for HDCP 1.4 over MST connectors
From: Sean Paul Changes in v6: -Rebased on -tip -Disabled HDCP over MST on GEN12 -Addressed Lyude's review comments in the QUERY_STREAM_ENCRYPTION_STATUS patch Sean Paul (16): drm/i915: Fix sha_text population code drm/i915: Clear the repeater bit on HDCP disable drm/i915: WARN if HDCP signalling is enabled upon disable drm/i915: Intercept Aksv writes in the aux hooks drm/i915: Use the cpu_transcoder in intel_hdcp to toggle HDCP signalling drm/i915: Factor out hdcp->value assignments drm/i915: Protect workers against disappearing connectors drm/i915: Don't fully disable HDCP on a port if multiple pipes are using it drm/i915: Support DP MST in enc_to_dig_port() function drm/i915: Use ddi_update_pipe in intel_dp_mst drm/i915: Factor out HDCP shim functions from dp for use by dp_mst drm/i915: Plumb port through hdcp init drm/i915: Add connector to hdcp_shim->check_link() drm/mst: Add support for QUERY_STREAM_ENCRYPTION_STATUS MST sideband message drm/i915: Print HDCP version info for all connectors drm/i915: Add HDCP 1.4 support for MST connectors drivers/gpu/drm/drm_dp_mst_topology.c | 142 drivers/gpu/drm/i915/Makefile | 1 + drivers/gpu/drm/i915/display/intel_ddi.c | 29 +- drivers/gpu/drm/i915/display/intel_ddi.h | 2 + .../drm/i915/display/intel_display_debugfs.c | 21 +- .../drm/i915/display/intel_display_types.h| 30 +- drivers/gpu/drm/i915/display/intel_dp.c | 654 +-- drivers/gpu/drm/i915/display/intel_dp.h | 9 + drivers/gpu/drm/i915/display/intel_dp_hdcp.c | 743 ++ drivers/gpu/drm/i915/display/intel_dp_mst.c | 19 + drivers/gpu/drm/i915/display/intel_hdcp.c | 217 +++-- drivers/gpu/drm/i915/display/intel_hdcp.h | 2 +- drivers/gpu/drm/i915/display/intel_hdmi.c | 25 +- .../drm/selftests/test-drm_dp_mst_helper.c| 17 + include/drm/drm_dp_helper.h | 3 + include/drm/drm_dp_mst_helper.h | 44 ++ include/drm/drm_hdcp.h| 3 + 17 files changed, 1235 insertions(+), 726 deletions(-) create mode 100644 drivers/gpu/drm/i915/display/intel_dp_hdcp.c -- Sean Paul, Software Engineer, Google / Chromium OS ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [PATCH v2] video: fbdev: controlfb: fix build for COMPILE_TEST=y && PPC_PMAC=y && PPC32=n
Hi Bartlomiej On Wed, Apr 29, 2020 at 12:48:24PM +0200, Bartlomiej Zolnierkiewicz wrote: > > powerpc allyesconfig fails like this: > > drivers/video/fbdev/controlfb.c: In function 'controlfb_mmap': > drivers/video/fbdev/controlfb.c:756:23: error: implicit declaration of > function 'pgprot_cached_wthru'; did you mean 'pgprot_cached'? > [-Werror=implicit-function-declaration] > 756 | vma->vm_page_prot = pgprot_cached_wthru(vma->vm_page_prot); > | ^~~ > | pgprot_cached > drivers/video/fbdev/controlfb.c:756:23: error: incompatible types when > assigning to type 'pgprot_t' {aka 'struct '} from type 'int' > > Fix it by adding missing PPC32 dependency. > > Fixes: a07a63b0e24d ("video: fbdev: controlfb: add COMPILE_TEST support") > Reported-by: Stephen Rothwell > Reported-by: kbuild test robot > Cc: Sam Ravnborg > Cc: Daniel Vetter > Signed-off-by: Bartlomiej Zolnierkiewicz I've updated my build script to include a few popwerpc 32 bit configs. Patch looked correct, and my builds was OK. So applied to drm-misc-next and pushed out. If my prodding of Christoph will result in anything only time will tell. Sam > --- > v2: fix implicit btext_update_display() function declaration error > > drivers/video/fbdev/controlfb.c |2 +- > 1 file changed, 1 insertion(+), 1 deletion(-) > > Index: b/drivers/video/fbdev/controlfb.c > === > --- a/drivers/video/fbdev/controlfb.c > +++ b/drivers/video/fbdev/controlfb.c > @@ -55,7 +55,7 @@ > #include "macmodes.h" > #include "controlfb.h" > > -#ifndef CONFIG_PPC_PMAC > +#if !defined(CONFIG_PPC_PMAC) || !defined(CONFIG_PPC32) > #define invalid_vram_cache(addr) > #undef in_8 > #undef out_8 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [PATCH] misc: sram: Add dma-heap-export reserved SRAM area type
On 4/27/20 11:17 AM, Rob Herring wrote: > On Fri, Apr 24, 2020 at 5:27 PM Andrew F. Davis wrote: >> >> This new export type exposes to userspace the SRAM area as a DMA-Heap, >> this allows for allocations as DMA-BUFs that can be consumed by various >> DMA-BUF supporting devices. >> >> Signed-off-by: Andrew F. Davis >> --- >> .../devicetree/bindings/sram/sram.yaml| 8 + > > Separate patch and needs to go to DT list... > Okay, will split for v2. >> drivers/misc/Kconfig | 7 + >> drivers/misc/Makefile | 1 + >> drivers/misc/sram-dma-heap.c | 243 ++ >> drivers/misc/sram.c | 20 +- >> drivers/misc/sram.h | 17 ++ >> 6 files changed, 292 insertions(+), 4 deletions(-) >> create mode 100644 drivers/misc/sram-dma-heap.c >> >> diff --git a/Documentation/devicetree/bindings/sram/sram.yaml >> b/Documentation/devicetree/bindings/sram/sram.yaml >> index 7b83cc6c9bfa..b8e33c8d205d 100644 >> --- a/Documentation/devicetree/bindings/sram/sram.yaml >> +++ b/Documentation/devicetree/bindings/sram/sram.yaml >> @@ -105,6 +105,14 @@ patternProperties: >>manipulation of the page attributes. >> type: boolean >> >> + dma-heap-export: >> +description: >> + Similar to 'pool' and 'export' this region will be exported for >> use >> + by drivers, devices, and userspace using the DMA-Heaps framework. >> + NOTE: This region must be page aligned on start and end in order >> to >> + properly allow manipulation of the page attributes. >> +type: boolean > > Though I'm not sure this should be in DT. You have to change your > firmware to enable a new kernel feature? We also already have 'export' > which sounds like the same function. Or 'pool' though reading the > description, I don't really understand it's use. > Maybe I could just re-use 'export', right now that property causes the SRAM region to be exported to userspace as a file one can read/write. Exporting via dma-heaps/dma-buf allows more flexibility as one can pass the exported regions to other devices or mmap them directly in userspace. It's up to the SRAM driver maintainer if re-purposing that property in the driver is acceptable. 'Pool' doesn't make much sense to me either, it creates a gen-pool out of the region, but I cant find any users not in combination with the other properties. > What combination of all 3 of these options would be valid? > >From looking at the SRAM driver, it seems each of the option must be used exclusively per region, combining will cause issues. I can update the documentation for the same after we settle on a strategy for this new property. Andrew > Rob > ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [PATCH v5 1/3] dt-bindings: phy: qcom,qmp: Convert QMP PHY bindings to yaml
Hi Sandeep, On Thu, Apr 23, 2020 at 10:14:36AM -0700, Matthias Kaehlcke wrote: > Hi Sandeep, > > On Tue, Apr 14, 2020 at 02:21:17PM -0700, Stephen Boyd wrote: > > Quoting Sandeep Maheswaram (2020-04-01 23:38:52) > > > Convert QMP PHY bindings to DT schema format using json-schema. > > > > > > Signed-off-by: Sandeep Maheswaram > > > --- > > > .../devicetree/bindings/phy/qcom,qmp-phy.yaml | 332 > > > + > > > .../devicetree/bindings/phy/qcom-qmp-phy.txt | 242 --- > > > 2 files changed, 332 insertions(+), 242 deletions(-) > > > create mode 100644 > > > Documentation/devicetree/bindings/phy/qcom,qmp-phy.yaml > > > delete mode 100644 Documentation/devicetree/bindings/phy/qcom-qmp-phy.txt > > > > > > diff --git a/Documentation/devicetree/bindings/phy/qcom,qmp-phy.yaml > > > b/Documentation/devicetree/bindings/phy/qcom,qmp-phy.yaml > > > new file mode 100644 > > > index 000..18a8985 > > > --- /dev/null > > > +++ b/Documentation/devicetree/bindings/phy/qcom,qmp-phy.yaml > > > @@ -0,0 +1,332 @@ > > > +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) > > > + > > > +%YAML 1.2 > > > +--- > > > +$id: "http://devicetree.org/schemas/phy/qcom,qmp-phy.yaml#; > > > +$schema: "http://devicetree.org/meta-schemas/core.yaml#; > > > + > > > +title: Qualcomm QMP PHY controller > > > + > > > +maintainers: > > > + - Manu Gautam > > > + > > > +description: > > > + QMP phy controller supports physical layer functionality for a number > > > of > > > + controllers on Qualcomm chipsets, such as, PCIe, UFS, and USB. > > > + > > > +properties: > > > + compatible: > > > +enum: > > > + - qcom,ipq8074-qmp-pcie-phy > > > + - qcom,msm8996-qmp-pcie-phy > > > + - qcom,msm8996-qmp-ufs-phy > > > + - qcom,msm8996-qmp-usb3-phy > > > + - qcom,msm8998-qmp-pcie-phy > > > + - qcom,msm8998-qmp-ufs-phy > > > + - qcom,msm8998-qmp-usb3-phy > > > + - qcom,sdm845-qhp-pcie-phy > > > + - qcom,sdm845-qmp-pcie-phy > > > + - qcom,sdm845-qmp-ufs-phy > > > + - qcom,sdm845-qmp-usb3-phy > > > + - qcom,sdm845-qmp-usb3-uni-phy > > > + - qcom,sm8150-qmp-ufs-phy > > > + > > > + reg: > > > +minItems: 1 > > > +items: > > > + - description: Address and length of PHY's common serdes block. > > > + - description: Address and length of the DP_COM control block. > > > > This DP_COM block is only for one compatible. Is it possible to split > > that compatible out of this binding so we can enforce the reg property > > being either one or two items? > > > > In addition, I don't quite understand how this binding is supposed to > > work with the DP phy that sits inside qcom,sdm845-qmp-usb3-phy and then > > gets muxed out on the USB pins on sdm845 and sc7180 SoCs. Can you fill > > me in on how we plan to share the pins between the two phys so that all > > the combinations of DP and USB over the type-c pins will work here? My > > understanding is that the pins that are controlled by this hardware > > block are basically a full USB type-c connector pinout[1] (except that > > D+/D- isn't there and the VBUS and CC lines go to the PMIC). Either way, > > we get the TX1/2 and RX1/2 pins to use, so we can do 4x lanes of DP or > > 2x lanes DP and 2x lanes of USB. There's also a type-c orientation > > flipper bit that can flip the DP and USB phy lanes to the correct TX/RX > > pins on the SoC. And then the DP phy has a lane remapper to change the > > logical DP lane to the physical DP lane. It's a complex piece of > > hardware that isn't fully represented by this binding. > > > > [1] > > https://en.wikipedia.org/wiki/USB-C#/media/File:USB_Type-C_Receptacle_Pinout.svg > > Could you please answer Stephen's questions? It would be great to move > forward and get support for SC7180 landed. You posted v6, which does the split Stephen asked for, but you didn't answer his question about the pin sharing. Since this is an existing binding there is probably no reason to block it from landing, but it would still be good to clarify this. Thanks Matthias ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [PATCH] drm: Correct DP DSC macro typo
On 2020-04-29 2:41 p.m., Rodrigo Siqueira wrote: > In the file drm_dp_helper.h we have a macro named > DP_DSC_THROUGHPUT_MODE_{0,1}_UPSUPPORTED, the correct name should be > DP_DSC_THROUGHPUT_MODE_{0,1}_UNSUPPORTED. This commits adjusts this typo > in the header file and in other places that attempt to access this > macro. > > Signed-off-by: Rodrigo Siqueira Reviewed-by: Harry Wentland Harry > --- > drivers/gpu/drm/amd/display/dc/dsc/dc_dsc.c | 2 +- > include/drm/drm_dp_helper.h | 4 ++-- > 2 files changed, 3 insertions(+), 3 deletions(-) > > diff --git a/drivers/gpu/drm/amd/display/dc/dsc/dc_dsc.c > b/drivers/gpu/drm/amd/display/dc/dsc/dc_dsc.c > index 87d682d25278..0ea6662a1563 100644 > --- a/drivers/gpu/drm/amd/display/dc/dsc/dc_dsc.c > +++ b/drivers/gpu/drm/amd/display/dc/dsc/dc_dsc.c > @@ -129,7 +129,7 @@ static bool dsc_line_buff_depth_from_dpcd(int > dpcd_line_buff_bit_depth, int *lin > static bool dsc_throughput_from_dpcd(int dpcd_throughput, int *throughput) > { > switch (dpcd_throughput) { > - case DP_DSC_THROUGHPUT_MODE_0_UPSUPPORTED: > + case DP_DSC_THROUGHPUT_MODE_0_UNSUPPORTED: > *throughput = 0; > break; > case DP_DSC_THROUGHPUT_MODE_0_170: > diff --git a/include/drm/drm_dp_helper.h b/include/drm/drm_dp_helper.h > index c6119e4c169a..fd7ac8f15004 100644 > --- a/include/drm/drm_dp_helper.h > +++ b/include/drm/drm_dp_helper.h > @@ -292,7 +292,7 @@ > #define DP_DSC_PEAK_THROUGHPUT 0x06B > # define DP_DSC_THROUGHPUT_MODE_0_MASK (0xf << 0) > # define DP_DSC_THROUGHPUT_MODE_0_SHIFT 0 > -# define DP_DSC_THROUGHPUT_MODE_0_UPSUPPORTED 0 > +# define DP_DSC_THROUGHPUT_MODE_0_UNSUPPORTED 0 > # define DP_DSC_THROUGHPUT_MODE_0_340 (1 << 0) > # define DP_DSC_THROUGHPUT_MODE_0_400 (2 << 0) > # define DP_DSC_THROUGHPUT_MODE_0_450 (3 << 0) > @@ -310,7 +310,7 @@ > # define DP_DSC_THROUGHPUT_MODE_0_170 (15 << 0) /* 1.4a */ > # define DP_DSC_THROUGHPUT_MODE_1_MASK (0xf << 4) > # define DP_DSC_THROUGHPUT_MODE_1_SHIFT 4 > -# define DP_DSC_THROUGHPUT_MODE_1_UPSUPPORTED 0 > +# define DP_DSC_THROUGHPUT_MODE_1_UNSUPPORTED 0 > # define DP_DSC_THROUGHPUT_MODE_1_340 (1 << 4) > # define DP_DSC_THROUGHPUT_MODE_1_400 (2 << 4) > # define DP_DSC_THROUGHPUT_MODE_1_450 (3 << 4) > ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH] drm: Correct DP DSC macro typo
In the file drm_dp_helper.h we have a macro named DP_DSC_THROUGHPUT_MODE_{0,1}_UPSUPPORTED, the correct name should be DP_DSC_THROUGHPUT_MODE_{0,1}_UNSUPPORTED. This commits adjusts this typo in the header file and in other places that attempt to access this macro. Signed-off-by: Rodrigo Siqueira --- drivers/gpu/drm/amd/display/dc/dsc/dc_dsc.c | 2 +- include/drm/drm_dp_helper.h | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dsc/dc_dsc.c b/drivers/gpu/drm/amd/display/dc/dsc/dc_dsc.c index 87d682d25278..0ea6662a1563 100644 --- a/drivers/gpu/drm/amd/display/dc/dsc/dc_dsc.c +++ b/drivers/gpu/drm/amd/display/dc/dsc/dc_dsc.c @@ -129,7 +129,7 @@ static bool dsc_line_buff_depth_from_dpcd(int dpcd_line_buff_bit_depth, int *lin static bool dsc_throughput_from_dpcd(int dpcd_throughput, int *throughput) { switch (dpcd_throughput) { - case DP_DSC_THROUGHPUT_MODE_0_UPSUPPORTED: + case DP_DSC_THROUGHPUT_MODE_0_UNSUPPORTED: *throughput = 0; break; case DP_DSC_THROUGHPUT_MODE_0_170: diff --git a/include/drm/drm_dp_helper.h b/include/drm/drm_dp_helper.h index c6119e4c169a..fd7ac8f15004 100644 --- a/include/drm/drm_dp_helper.h +++ b/include/drm/drm_dp_helper.h @@ -292,7 +292,7 @@ #define DP_DSC_PEAK_THROUGHPUT 0x06B # define DP_DSC_THROUGHPUT_MODE_0_MASK (0xf << 0) # define DP_DSC_THROUGHPUT_MODE_0_SHIFT 0 -# define DP_DSC_THROUGHPUT_MODE_0_UPSUPPORTED 0 +# define DP_DSC_THROUGHPUT_MODE_0_UNSUPPORTED 0 # define DP_DSC_THROUGHPUT_MODE_0_340 (1 << 0) # define DP_DSC_THROUGHPUT_MODE_0_400 (2 << 0) # define DP_DSC_THROUGHPUT_MODE_0_450 (3 << 0) @@ -310,7 +310,7 @@ # define DP_DSC_THROUGHPUT_MODE_0_170 (15 << 0) /* 1.4a */ # define DP_DSC_THROUGHPUT_MODE_1_MASK (0xf << 4) # define DP_DSC_THROUGHPUT_MODE_1_SHIFT 4 -# define DP_DSC_THROUGHPUT_MODE_1_UPSUPPORTED 0 +# define DP_DSC_THROUGHPUT_MODE_1_UNSUPPORTED 0 # define DP_DSC_THROUGHPUT_MODE_1_340 (1 << 4) # define DP_DSC_THROUGHPUT_MODE_1_400 (2 << 4) # define DP_DSC_THROUGHPUT_MODE_1_450 (3 << 4) -- 2.26.2 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [PATCH 02/10] drm: Add backlight helper
Den 29.04.2020 16.13, skrev Hans de Goede: > Hi Noralf, > > On 4/29/20 2:48 PM, Noralf Trønnes wrote: >> This adds a function that creates a backlight device for a connector. >> It does not deal with the KMS backlight ABI proposition[1] to add a >> connector property. It only takes the current best practise to >> standardise >> the creation of a backlight device for DRM drivers while we wait for the >> property. >> >> The brightness value is set using a connector state variable and an >> atomic >> commit. >> >> I have looked through some of the backlight users and this is what >> I've found: >> >> GNOME [2] >> - >> >> Brightness range: 0-100 >> Scale: Assumes perceptual > > I'm afraid that this is an incaccurate view of how GNOME handles the > brightness. gnome-settings-daemon (g-s-d) exports a DBUS property which has > a range of 0 - 100%. But it also offers step-up and step-down DBUS methods > which are used for handling brightness hotkey presses. > > This is important because g-s-d internally also keeps a step_size variable > which depends on the brightness_max value of the sysfs backlight interface, > like this: > > BRIGHTNESS_STEP_AMOUNT(max) ((max) < 20 ? 1 : (max) / 20) > > This is important because some older laptops where we depend on the > vendor specific ACPI method (from e.g. dell-laptop or thinkpad_acpi) > there are only 8 levels. So if g-s-d where to simply fake a 1-100 > range and would leave the stepping up to the DBus API user and that > user would want 20 steps, so 5 % per step, then the user would get > > Start -> 100% -> level 8 > Press down -> 95% -> level 7 > Press down -> 90% -> level 7 *no change* > etc. > > Somewhat related on some embedded ARM devices there are tricks where > when the entire scene being rendered does not use 100% white as color, > the entire scene has all its rgb values upscaled (too a curve) so that > the brightest colors do hit 100% of one of r/g/b, combined with dimming > the backlight a bit to save power. As you can imagine for tricks like > these you want as much backlight control precision as possible. > > So any backlight infra we add must expose the true range of the > backlight control and not normalize it to a 0-100 range. > > So sorry, but nack for the current version because of the hardcoding > of the range. No problem, I just had to start from somewhere, and I started with: Give the driver developer as few options as possible, no more than necessary, but I didn't really know what was necessary :-) The reason I chose a 0-100 range is because the backlight property ABI proposal had this range and it maps so nicely to percent. And can the ordinary human see brightness changes in more than 100 steps? This helper is only to be used by drm drivers and I assumed that all the current drivers registering a backlight device could at least do that range. Looking through the drivers and their max_brightness values that assumption isn't quite right: amd: 255 gma500: 100 i915: nouveau/nv40: 31 nouveau/nv50: 100 radeon: 255 shmobile: panel-dsi-cm.c: 255 panel-jdi-lt070me05000.c: 255 panel-orisetech-otm8009a.c: 255 panel-raydium-rm67191.c: 255 panel-samsung-s6e63m0.c: 10 panel-sony-acx424akp.c: 1023 panel-samsung-s6e3ha2.c: 100 panel-samsung-s6e63j0x03.c: 100 panel-sony-acx565akm.c: 255 bridge/parade-ps8622.c: 255 I'll add max_brightness as an argument together with scale which you commented on below. > > Also the scale really should be specified by the driver, or be hardcoded > to BACKLIGHT_SCALE_UNKNOWN for now. In many cases we do not really know. > But for e.g. the acpi_video firmware backlight interface a good guess is > that it actually represents a perceptual scale rather then controlling > the wattage. > > Where as the native i915 backlight interface really is controlling > the wattage without any perceptual correction. > > Another problem with your proposal is that it seems to assume that > the backlight is controlled by the drm/kms driver. On x86 we have Yes, this backlight device is just for drm drivers. The reason I spend time on this is because I want to pass backlight brightness changes through the atomic machinery like any other state change. Noralf. > atleast 3 different drivers for the backlight: > > 1) The i915 (or amd/nouveau) native driver which more or less > directly pokes the PWM controller of the GPU. > 2) The ACPI video standard backlight interface > 3) Vendor specific ACPI interfaces from older laptops > > ATM we always register 1. which could remain unchanged with > your code and then also register 2/3 if we (the kernel) think > that will work better (*) and then rely on userspace prefering > these (they have a different backlight_type) over 1. > > Ideally any infra we add will also offer the option to tie > 2. or 3. to the connector... > > Regards, > > Hans > > > > *) e.g. it will work while the others will not work at all > > > > >> >> Avoids setting the sysfs brightness value to
Re: [PATCH 07/17] drm/mgag200: Move mode-setting code into separate helper function
On Wed, Apr 29, 2020 at 04:32:28PM +0200, Thomas Zimmermann wrote: > The mode-setting code is now located in mgag200_set_mode_regs(), sans > a few flags that will be moved in a later patch for clarity. > > Signed-off-by: Thomas Zimmermann Looked like trivial code movements, did not look carefully. Acked-by: Sam Ravnborg > --- > drivers/gpu/drm/mgag200/mgag200_mode.c | 140 ++--- > 1 file changed, 78 insertions(+), 62 deletions(-) > > diff --git a/drivers/gpu/drm/mgag200/mgag200_mode.c > b/drivers/gpu/drm/mgag200/mgag200_mode.c > index 12df809d64f7c..749ba6e420ac7 100644 > --- a/drivers/gpu/drm/mgag200/mgag200_mode.c > +++ b/drivers/gpu/drm/mgag200/mgag200_mode.c > @@ -911,6 +911,79 @@ static int mga_crtc_mode_set_base(struct drm_crtc *crtc, > int x, int y, > return mga_crtc_do_set_base(mdev, fb, old_fb); > } > > +static void mgag200_set_mode_regs(struct mga_device *mdev, > + const struct drm_display_mode *mode) > +{ > + unsigned int hdisplay, hsyncstart, hsyncend, htotal; > + unsigned int vdisplay, vsyncstart, vsyncend, vtotal; > + uint8_t misc = 0; > + uint8_t crtcext1, crtcext2, crtcext5; > + > + hdisplay = mode->hdisplay / 8 - 1; > + hsyncstart = mode->hsync_start / 8 - 1; > + hsyncend = mode->hsync_end / 8 - 1; > + htotal = mode->htotal / 8 - 1; > + > + /* Work around hardware quirk */ > + if ((htotal & 0x07) == 0x06 || (htotal & 0x07) == 0x04) > + htotal++; > + > + vdisplay = mode->vdisplay - 1; > + vsyncstart = mode->vsync_start - 1; > + vsyncend = mode->vsync_end - 1; > + vtotal = mode->vtotal - 2; > + > + if (mode->flags & DRM_MODE_FLAG_NHSYNC) > + misc |= 0x40; > + if (mode->flags & DRM_MODE_FLAG_NVSYNC) > + misc |= 0x80; > + > + crtcext1 = (((htotal - 4) & 0x100) >> 8) | > +((hdisplay & 0x100) >> 7) | > +((hsyncstart & 0x100) >> 6) | > + (htotal & 0x40); > + if (mdev->type == G200_WB || mdev->type == G200_EW3) > + crtcext1 |= BIT(7) | /* vrsten */ > + BIT(3); /* hrsten */ > + > + crtcext2 = ((vtotal & 0xc00) >> 10) | > +((vdisplay & 0x400) >> 8) | > +((vdisplay & 0xc00) >> 7) | > +((vsyncstart & 0xc00) >> 5) | > +((vdisplay & 0x400) >> 3); > + crtcext5 = 0x00; > + > + WREG_CRT(0, htotal - 4); > + WREG_CRT(1, hdisplay); > + WREG_CRT(2, hdisplay); > + WREG_CRT(3, (htotal & 0x1F) | 0x80); > + WREG_CRT(4, hsyncstart); > + WREG_CRT(5, ((htotal & 0x20) << 2) | (hsyncend & 0x1F)); > + WREG_CRT(6, vtotal & 0xFF); > + WREG_CRT(7, ((vtotal & 0x100) >> 8) | > + ((vdisplay & 0x100) >> 7) | > + ((vsyncstart & 0x100) >> 6) | > + ((vdisplay & 0x100) >> 5) | > + ((vdisplay & 0x100) >> 4) | /* linecomp */ > + ((vtotal & 0x200) >> 4) | > + ((vdisplay & 0x200) >> 3) | > + ((vsyncstart & 0x200) >> 2)); > + WREG_CRT(9, ((vdisplay & 0x200) >> 4) | > + ((vdisplay & 0x200) >> 3)); > + WREG_CRT(16, vsyncstart & 0xFF); > + WREG_CRT(17, (vsyncend & 0x0F) | 0x20); > + WREG_CRT(18, vdisplay & 0xFF); > + WREG_CRT(20, 0); > + WREG_CRT(21, vdisplay & 0xFF); > + WREG_CRT(22, (vtotal + 1) & 0xFF); > + WREG_CRT(23, 0xc3); > + WREG_CRT(24, vdisplay & 0xFF); > + > + WREG_ECRT(0x01, crtcext1); > + WREG_ECRT(0x02, crtcext2); > + WREG_ECRT(0x05, crtcext5); > +} > + > static int mga_crtc_mode_set(struct drm_crtc *crtc, > struct drm_display_mode *mode, > struct drm_display_mode *adjusted_mode, > @@ -919,8 +992,6 @@ static int mga_crtc_mode_set(struct drm_crtc *crtc, > struct drm_device *dev = crtc->dev; > struct mga_device *mdev = dev->dev_private; > const struct drm_framebuffer *fb = crtc->primary->fb; > - int hdisplay, hsyncstart, hsyncend, htotal; > - int vdisplay, vsyncstart, vsyncend, vtotal; > int pitch; > int option = 0, option2 = 0; > int i; > @@ -999,12 +1070,6 @@ static int mga_crtc_mode_set(struct drm_crtc *crtc, > break; > } > > - if (mode->flags & DRM_MODE_FLAG_NHSYNC) > - misc |= 0x40; > - if (mode->flags & DRM_MODE_FLAG_NVSYNC) > - misc |= 0x80; > - > - > for (i = 0; i < sizeof(dacvalue); i++) { > if ((i <= 0x17) || > (i == 0x1b) || > @@ -1044,20 +1109,6 @@ static int mga_crtc_mode_set(struct drm_crtc *crtc, > else > pitch = pitch >> (4 - bppshift); > > - hdisplay = mode->hdisplay / 8 - 1; > - hsyncstart = mode->hsync_start / 8 - 1; > - hsyncend = mode->hsync_end / 8 - 1; > - htotal = mode->htotal / 8 - 1; > - > - /* Work around hardware quirk */ > - if ((htotal & 0x07) == 0x06
Re: [PATCH 06/17] drm/mgag200: Clean up mga_crtc_do_set_base()
On Wed, Apr 29, 2020 at 04:32:27PM +0200, Thomas Zimmermann wrote: > The function now only takes the device structure, and the old and new > framebuffers. > > Signed-off-by: Thomas Zimmermann Acked-by: Sam Ravnborg > --- > drivers/gpu/drm/mgag200/mgag200_mode.c | 18 +- > 1 file changed, 9 insertions(+), 9 deletions(-) > > diff --git a/drivers/gpu/drm/mgag200/mgag200_mode.c > b/drivers/gpu/drm/mgag200/mgag200_mode.c > index b16a73c8617d6..12df809d64f7c 100644 > --- a/drivers/gpu/drm/mgag200/mgag200_mode.c > +++ b/drivers/gpu/drm/mgag200/mgag200_mode.c > @@ -861,21 +861,20 @@ static void mgag200_set_startadd(struct mga_device > *mdev, > WREG_ECRT(0x00, crtcext0); > } > > -static int mga_crtc_do_set_base(struct drm_crtc *crtc, > - struct drm_framebuffer *fb, > - int x, int y, int atomic) > +static int mga_crtc_do_set_base(struct mga_device *mdev, > + const struct drm_framebuffer *fb, > + const struct drm_framebuffer *old_fb) > { > - struct mga_device *mdev = crtc->dev->dev_private; > struct drm_gem_vram_object *gbo; > int ret; > s64 gpu_addr; > > - if (!atomic && fb) { > - gbo = drm_gem_vram_of_gem(fb->obj[0]); > + if (old_fb) { > + gbo = drm_gem_vram_of_gem(old_fb->obj[0]); > drm_gem_vram_unpin(gbo); > } > > - gbo = drm_gem_vram_of_gem(crtc->primary->fb->obj[0]); > + gbo = drm_gem_vram_of_gem(fb->obj[0]); > > ret = drm_gem_vram_pin(gbo, DRM_GEM_VRAM_PL_FLAG_VRAM); > if (ret) > @@ -900,6 +899,7 @@ static int mga_crtc_mode_set_base(struct drm_crtc *crtc, > int x, int y, > { > struct drm_device *dev = crtc->dev; > struct mga_device *mdev = dev->dev_private; > + struct drm_framebuffer *fb = crtc->primary->fb; > unsigned int count; > > while (RREG8(0x1fda) & 0x08) { } > @@ -908,7 +908,7 @@ static int mga_crtc_mode_set_base(struct drm_crtc *crtc, > int x, int y, > count = RREG8(MGAREG_VCOUNT) + 2; > while (RREG8(MGAREG_VCOUNT) < count) { } > > - return mga_crtc_do_set_base(crtc, old_fb, x, y, 0); > + return mga_crtc_do_set_base(mdev, fb, old_fb); > } > > static int mga_crtc_mode_set(struct drm_crtc *crtc, > @@ -1150,7 +1150,7 @@ static int mga_crtc_mode_set(struct drm_crtc *crtc, > > WREG8(MGA_MISC_OUT, misc); > > - mga_crtc_do_set_base(crtc, old_fb, x, y, 0); > + mga_crtc_do_set_base(mdev, fb, old_fb); > > /* reset tagfifo */ > if (mdev->type == G200_ER) { > -- > 2.26.0 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [PATCH 05/17] drm/mgag200: Clean up mga_set_start_address()
Hi Thomas, On Wed, Apr 29, 2020 at 04:32:26PM +0200, Thomas Zimmermann wrote: > All register names and fields are now named according to the > MGA programming manuals. The function doesn't need the CRTC, so > callers pass in the device structure directly. The logging now > uses device-specific macros. > > Signed-off-by: Thomas Zimmermann > --- > drivers/gpu/drm/mgag200/mgag200_drv.h | 5 ++ > drivers/gpu/drm/mgag200/mgag200_mode.c | 82 +++--- > 2 files changed, 53 insertions(+), 34 deletions(-) > > diff --git a/drivers/gpu/drm/mgag200/mgag200_drv.h > b/drivers/gpu/drm/mgag200/mgag200_drv.h > index 4403145e3593c..9b957d9fc7e04 100644 > --- a/drivers/gpu/drm/mgag200/mgag200_drv.h > +++ b/drivers/gpu/drm/mgag200/mgag200_drv.h > @@ -61,6 +61,11 @@ > WREG8(MGAREG_CRTC_DATA, v); \ > } while (0) \ > > +#define RREG_ECRT(reg, v)\ > + do {\ > + WREG8(MGAREG_CRTCEXT_INDEX, reg); \ > + v = RREG8(MGAREG_CRTCEXT_DATA); \ > + } while (0) \ > > #define WREG_ECRT(reg, v)\ > do {\ > diff --git a/drivers/gpu/drm/mgag200/mgag200_mode.c > b/drivers/gpu/drm/mgag200/mgag200_mode.c > index 3d894b37a0812..b16a73c8617d6 100644 > --- a/drivers/gpu/drm/mgag200/mgag200_mode.c > +++ b/drivers/gpu/drm/mgag200/mgag200_mode.c > @@ -819,49 +819,53 @@ static void mga_g200wb_commit(struct drm_crtc *crtc) > } > > /* > - This is how the framebuffer base address is stored in g200 cards: > - * Assume @offset is the gpu_addr variable of the framebuffer object > - * Then addr is the number of _pixels_ (not bytes) from the start of > - VRAM to the first pixel we want to display. (divided by 2 for 32bit > - framebuffers) > - * addr is stored in the CRTCEXT0, CRTCC and CRTCD registers > - addr<20> -> CRTCEXT0<6> > - addr<19-16> -> CRTCEXT0<3-0> > - addr<15-8> -> CRTCC<7-0> > - addr<7-0> -> CRTCD<7-0> > - CRTCEXT0 has to be programmed last to trigger an update and make the > - new addr variable take effect. > + * This is how the framebuffer base address is stored in g200 cards: > + * * Assume @offset is the gpu_addr variable of the framebuffer object > + * * Then addr is the number of _pixels_ (not bytes) from the start of > + * VRAM to the first pixel we want to display. (divided by 2 for 32bit > + * framebuffers) > + * * addr is stored in the CRTCEXT0, CRTCC and CRTCD registers > + * addr<20> -> CRTCEXT0<6> > + * addr<19-16> -> CRTCEXT0<3-0> > + * addr<15-8> -> CRTCC<7-0> > + * addr<7-0> -> CRTCD<7-0> > + * > + * CRTCEXT0 has to be programmed last to trigger an update and make the > + * new addr variable take effect. > */ > -static void mga_set_start_address(struct drm_crtc *crtc, unsigned offset) > +static void mgag200_set_startadd(struct mga_device *mdev, > + unsigned long offset) > { > - struct mga_device *mdev = crtc->dev->dev_private; > - u32 addr; > - int count; > - u8 crtcext0; > + struct drm_device *dev = mdev->dev; > + uint32_t startadd; > + uint8_t crtcc, crtcd, crtcext0; > > - while (RREG8(0x1fda) & 0x08); > - while (!(RREG8(0x1fda) & 0x08)); > + startadd = offset / 8; > > - count = RREG8(MGAREG_VCOUNT) + 2; > - while (RREG8(MGAREG_VCOUNT) < count); > - > - WREG8(MGAREG_CRTCEXT_INDEX, 0); > - crtcext0 = RREG8(MGAREG_CRTCEXT_DATA); > - crtcext0 &= 0xB0; > - addr = offset / 8; > - /* Can't store addresses any higher than that... > -but we also don't have more than 16MB of memory, so it should be > fine. */ > - WARN_ON(addr > 0x1f); > - crtcext0 |= (!!(addr & (1<<20)))<<6; > - WREG_CRT(0x0d, (u8)(addr & 0xff)); > - WREG_CRT(0x0c, (u8)(addr >> 8) & 0xff); > - WREG_ECRT(0x0, ((u8)(addr >> 16) & 0xf) | crtcext0); > + /* > + * Can't store addresses any higher than that, but we also > + * don't have more than 16MB of memory, so it should be fine. > + */ > + drm_WARN_ON(dev, startadd > 0x1f); > + > + RREG_ECRT(0x00, crtcext0); > + > + crtcc = (startadd >> 8) & 0xff; > + crtcd = startadd & 0xff; > + crtcext0 &= 0xb0; > + crtcext0 |= ((startadd >> 14) & BIT(6)) | It is not so obvious that the value of bit 20 is stored in bit 6 here. Maybe: crtcext0 |= ((startadd & BIT(20) >> 14) | I would find the above easier to parse. > + ((startadd >> 16) & 0x0f); > + > + WREG_CRT(0x0c, crtcc); > + WREG_CRT(0x0d, crtcd); > + WREG_ECRT(0x00, crtcext0); > } > > static int mga_crtc_do_set_base(struct drm_crtc *crtc, > struct drm_framebuffer
Re: [PATCH 04/17] drm/mgag200: Use managed mode-config initialization
On Wed, Apr 29, 2020 at 04:32:25PM +0200, Thomas Zimmermann wrote: > Signed-off-by: Thomas Zimmermann Nice simplification. Changelog could be a bit more descriptive... Anyway: Acked-by: Sam Ravnborg > --- > drivers/gpu/drm/mgag200/mgag200_drv.h | 1 - > drivers/gpu/drm/mgag200/mgag200_main.c | 18 - > drivers/gpu/drm/mgag200/mgag200_mode.c | 37 -- > 3 files changed, 29 insertions(+), 27 deletions(-) > > diff --git a/drivers/gpu/drm/mgag200/mgag200_drv.h > b/drivers/gpu/drm/mgag200/mgag200_drv.h > index 09b43a0ff6bbf..4403145e3593c 100644 > --- a/drivers/gpu/drm/mgag200/mgag200_drv.h > +++ b/drivers/gpu/drm/mgag200/mgag200_drv.h > @@ -182,7 +182,6 @@ mgag200_flags_from_driver_data(kernel_ulong_t driver_data) > > /* mgag200_mode.c */ > int mgag200_modeset_init(struct mga_device *mdev); > -void mgag200_modeset_fini(struct mga_device *mdev); > > /* mgag200_main.c */ > int mgag200_driver_load(struct drm_device *dev, unsigned long flags); > diff --git a/drivers/gpu/drm/mgag200/mgag200_main.c > b/drivers/gpu/drm/mgag200/mgag200_main.c > index 698fbf31337d4..cf25012f9b6ec 100644 > --- a/drivers/gpu/drm/mgag200/mgag200_main.c > +++ b/drivers/gpu/drm/mgag200/mgag200_main.c > @@ -10,15 +10,8 @@ > > #include > > -#include > -#include > - > #include "mgag200_drv.h" > > -static const struct drm_mode_config_funcs mga_mode_funcs = { > - .fb_create = drm_gem_fb_create > -}; > - > static int mga_probe_vram(struct mga_device *mdev, void __iomem *mem) > { > int offset; > @@ -159,14 +152,6 @@ int mgag200_driver_load(struct drm_device *dev, unsigned > long flags) > if (r) > goto err_mm; > > - drm_mode_config_init(dev); > - dev->mode_config.funcs = (void *)_mode_funcs; > - if (IS_G200_SE(mdev) && mdev->vram_fb_available < (2048*1024)) > - dev->mode_config.preferred_depth = 16; > - else > - dev->mode_config.preferred_depth = 32; > - dev->mode_config.prefer_shadow = 1; > - > r = mgag200_modeset_init(mdev); > if (r) { > dev_err(>pdev->dev, "Fatal error during modeset init: > %d\n", r); > @@ -176,7 +161,6 @@ int mgag200_driver_load(struct drm_device *dev, unsigned > long flags) > return 0; > > err_modeset: > - drm_mode_config_cleanup(dev); > mgag200_mm_fini(mdev); > err_mm: > dev->dev_private = NULL; > @@ -190,8 +174,6 @@ void mgag200_driver_unload(struct drm_device *dev) > > if (mdev == NULL) > return; > - mgag200_modeset_fini(mdev); > - drm_mode_config_cleanup(dev); > mgag200_mm_fini(mdev); > dev->dev_private = NULL; > } > diff --git a/drivers/gpu/drm/mgag200/mgag200_mode.c > b/drivers/gpu/drm/mgag200/mgag200_mode.c > index eaa3fca7216ac..3d894b37a0812 100644 > --- a/drivers/gpu/drm/mgag200/mgag200_mode.c > +++ b/drivers/gpu/drm/mgag200/mgag200_mode.c > @@ -13,6 +13,7 @@ > > #include > #include > +#include > #include > #include > #include > @@ -1614,16 +1615,41 @@ static int mgag200_vga_connector_init(struct > mga_device *mdev) > return ret; > } > > +static const struct drm_mode_config_funcs mgag200_mode_config_funcs = { > + .fb_create = drm_gem_fb_create > +}; > + > +static unsigned int mgag200_preferred_depth(struct mga_device *mdev) > +{ > + if (IS_G200_SE(mdev) && mdev->vram_fb_available < (2048*1024)) > + return 16; > + else > + return 32; > +} > + > int mgag200_modeset_init(struct mga_device *mdev) > { > + struct drm_device *dev = mdev->dev; > struct drm_encoder *encoder = >encoder; > struct drm_connector *connector = >connector.base; > int ret; > > - mdev->dev->mode_config.max_width = MGAG200_MAX_FB_WIDTH; > - mdev->dev->mode_config.max_height = MGAG200_MAX_FB_HEIGHT; > + ret = drmm_mode_config_init(dev); > + if (ret) { > + drm_err(dev, "drmm_mode_config_init() failed, error %d\n", > + ret); > + return ret; > + } > + > + dev->mode_config.max_width = MGAG200_MAX_FB_WIDTH; > + dev->mode_config.max_height = MGAG200_MAX_FB_HEIGHT; > + > + dev->mode_config.preferred_depth = mgag200_preferred_depth(mdev); > + dev->mode_config.prefer_shadow = 1; > + > + dev->mode_config.fb_base = mdev->mc.vram_base; > > - mdev->dev->mode_config.fb_base = mdev->mc.vram_base; > + dev->mode_config.funcs = _mode_config_funcs; > > mga_crtc_init(mdev); > > @@ -1648,8 +1674,3 @@ int mgag200_modeset_init(struct mga_device *mdev) > > return 0; > } > - > -void mgag200_modeset_fini(struct mga_device *mdev) > -{ > - > -} > -- > 2.26.0 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [PATCH 01/17] drm/mgag200: Remove HW cursor
On Wed, Apr 29, 2020 at 04:32:22PM +0200, Thomas Zimmermann wrote: > The HW cursor of Matrox G200 cards only supports a 16-color palette > format. Univeral planes require at least ARGB or a similar component- > based format. Converting a cursor image from ARGB to 16 colors does not > produce pleasent-looking results in general, so remove the HW cursor. What impact does this have in useability? Does the cursor behaviour stay the same or? The patch looks fine, but it seems a bit gross ditching curcor support. But maybe it is the right choice, I dunno. Sam > > Signed-off-by: Thomas Zimmermann > --- > drivers/gpu/drm/mgag200/Makefile | 2 +- > drivers/gpu/drm/mgag200/mgag200_cursor.c | 319 --- > drivers/gpu/drm/mgag200/mgag200_drv.h| 13 - > drivers/gpu/drm/mgag200/mgag200_main.c | 7 - > drivers/gpu/drm/mgag200/mgag200_mode.c | 2 - > 5 files changed, 1 insertion(+), 342 deletions(-) > delete mode 100644 drivers/gpu/drm/mgag200/mgag200_cursor.c > > diff --git a/drivers/gpu/drm/mgag200/Makefile > b/drivers/gpu/drm/mgag200/Makefile > index 04b281bcf6558..63403133638a3 100644 > --- a/drivers/gpu/drm/mgag200/Makefile > +++ b/drivers/gpu/drm/mgag200/Makefile > @@ -1,5 +1,5 @@ > # SPDX-License-Identifier: GPL-2.0-only > -mgag200-y := mgag200_main.o mgag200_mode.o mgag200_cursor.o \ > +mgag200-y := mgag200_main.o mgag200_mode.o \ > mgag200_drv.o mgag200_i2c.o mgag200_ttm.o > > obj-$(CONFIG_DRM_MGAG200) += mgag200.o > diff --git a/drivers/gpu/drm/mgag200/mgag200_cursor.c > b/drivers/gpu/drm/mgag200/mgag200_cursor.c > deleted file mode 100644 > index d491edd317ff3..0 > --- a/drivers/gpu/drm/mgag200/mgag200_cursor.c > +++ /dev/null > @@ -1,319 +0,0 @@ > -// SPDX-License-Identifier: GPL-2.0-only > -/* > - * Copyright 2013 Matrox Graphics > - * > - * Author: Christopher Harvey > - */ > - > -#include > - > -#include "mgag200_drv.h" > - > -static bool warn_transparent = true; > -static bool warn_palette = true; > - > -static int mgag200_cursor_update(struct mga_device *mdev, void *dst, void > *src, > - unsigned int width, unsigned int height) > -{ > - struct drm_device *dev = mdev->dev; > - unsigned int i, row, col; > - uint32_t colour_set[16]; > - uint32_t *next_space = _set[0]; > - uint32_t *palette_iter; > - uint32_t this_colour; > - bool found = false; > - int colour_count = 0; > - u8 reg_index; > - u8 this_row[48]; > - > - memset(_set[0], 0, sizeof(uint32_t)*16); > - /* width*height*4 = 16384 */ > - for (i = 0; i < 16384; i += 4) { > - this_colour = ioread32(src + i); > - /* No transparency */ > - if (this_colour>>24 != 0xff && > - this_colour>>24 != 0x0) { > - if (warn_transparent) { > - dev_info(>pdev->dev, "Video card doesn't > support cursors with partial transparency.\n"); > - dev_info(>pdev->dev, "Not enabling > hardware cursor.\n"); > - warn_transparent = false; /* Only tell the user > once. */ > - } > - return -EINVAL; > - } > - /* Don't need to store transparent pixels as colours */ > - if (this_colour>>24 == 0x0) > - continue; > - found = false; > - for (palette_iter = _set[0]; palette_iter != next_space; > palette_iter++) { > - if (*palette_iter == this_colour) { > - found = true; > - break; > - } > - } > - if (found) > - continue; > - /* We only support 4bit paletted cursors */ > - if (colour_count >= 16) { > - if (warn_palette) { > - dev_info(>pdev->dev, "Video card only > supports cursors with up to 16 colours.\n"); > - dev_info(>pdev->dev, "Not enabling > hardware cursor.\n"); > - warn_palette = false; /* Only tell the user > once. */ > - } > - return -EINVAL; > - } > - *next_space = this_colour; > - next_space++; > - colour_count++; > - } > - > - /* Program colours from cursor icon into palette */ > - for (i = 0; i < colour_count; i++) { > - if (i <= 2) > - reg_index = 0x8 + i*0x4; > - else > - reg_index = 0x60 + i*0x3; > - WREG_DAC(reg_index, colour_set[i] & 0xff); > - WREG_DAC(reg_index+1, colour_set[i]>>8 & 0xff); > - WREG_DAC(reg_index+2, colour_set[i]>>16 & 0xff); > - BUG_ON((colour_set[i]>>24 & 0xff) != 0xff); > - } > - > - /* now write colour indices into hardware
Re: [PATCH 03/17] drm/mgag200: Embed connector instance in struct mga_device
Hi Thomas. On Wed, Apr 29, 2020 at 04:32:24PM +0200, Thomas Zimmermann wrote: > Storing the connector instance in struct mga_device avoids some > dynamic memory allocation. Done im preparation of converting > mgag200 to simple-KMS helpers. > > Signed-off-by: Thomas Zimmermann One nit below, with that fixed: Acked-by: Sam Ravnborg I expect to see mga_i2c_chan embedded in a later patch... Sam > --- > drivers/gpu/drm/mgag200/mgag200_drv.h | 1 + > drivers/gpu/drm/mgag200/mgag200_mode.c | 54 ++ > 2 files changed, 31 insertions(+), 24 deletions(-) > > diff --git a/drivers/gpu/drm/mgag200/mgag200_drv.h > b/drivers/gpu/drm/mgag200/mgag200_drv.h > index de3181bd63ca0..09b43a0ff6bbf 100644 > --- a/drivers/gpu/drm/mgag200/mgag200_drv.h > +++ b/drivers/gpu/drm/mgag200/mgag200_drv.h > @@ -164,6 +164,7 @@ struct mga_device { > /* SE model number stored in reg 0x1e24 */ > u32 unique_rev_id; > > + struct mga_connector connector; > struct drm_encoder encoder; > }; > > diff --git a/drivers/gpu/drm/mgag200/mgag200_mode.c > b/drivers/gpu/drm/mgag200/mgag200_mode.c > index ce41bebfdd1a2..eaa3fca7216ac 100644 > --- a/drivers/gpu/drm/mgag200/mgag200_mode.c > +++ b/drivers/gpu/drm/mgag200/mgag200_mode.c > @@ -1444,6 +1444,10 @@ static void mga_crtc_init(struct mga_device *mdev) > drm_crtc_helper_add(_crtc->base, _helper_funcs); > } > > +/* > + * Connector > + */ > + > static int mga_vga_get_modes(struct drm_connector *connector) > { > struct mga_connector *mga_connector = to_mga_connector(connector); > @@ -1568,7 +1572,6 @@ static void mga_connector_destroy(struct drm_connector > *connector) > struct mga_connector *mga_connector = to_mga_connector(connector); > mgag200_i2c_destroy(mga_connector->i2c); > drm_connector_cleanup(connector); > - kfree(connector); > } > > static const struct drm_connector_helper_funcs > mga_vga_connector_helper_funcs = { > @@ -1582,37 +1585,39 @@ static const struct drm_connector_funcs > mga_vga_connector_funcs = { > .destroy = mga_connector_destroy, > }; > > -static struct drm_connector *mga_vga_init(struct drm_device *dev) > +static int mgag200_vga_connector_init(struct mga_device *mdev) > { > - struct drm_connector *connector; > - struct mga_connector *mga_connector; > - > - mga_connector = kzalloc(sizeof(struct mga_connector), GFP_KERNEL); > - if (!mga_connector) > - return NULL; > - > - connector = _connector->base; > - mga_connector->i2c = mgag200_i2c_create(dev); > - if (!mga_connector->i2c) > - DRM_ERROR("failed to add ddc bus\n"); > + struct drm_device *dev = mdev->dev; > + struct mga_connector *mconnector = >connector; > + struct drm_connector *connector = >base; > + struct mga_i2c_chan *i2c; > + int ret; > > - drm_connector_init_with_ddc(dev, connector, > - _vga_connector_funcs, > - DRM_MODE_CONNECTOR_VGA, > - _connector->i2c->adapter); > + i2c = mgag200_i2c_create(dev); > + if (!i2c) > + drm_warn(dev, "failed to add DDC bus\n"); > > + ret = drm_connector_init_with_ddc(dev, connector, > + _vga_connector_funcs, > + DRM_MODE_CONNECTOR_VGA, > + >adapter); > + if (ret) > + goto err_mgag200_i2c_destroy; > drm_connector_helper_add(connector, _vga_connector_helper_funcs); > > - drm_connector_register(connector); > + mconnector->i2c = i2c; > > - return connector; > -} > + return 0; > > +err_mgag200_i2c_destroy: > + mgag200_i2c_destroy(i2c); > + return ret; > +} > > int mgag200_modeset_init(struct mga_device *mdev) > { > struct drm_encoder *encoder = >encoder; > - struct drm_connector *connector; > + struct drm_connector *connector = >connector.base; > int ret; > > mdev->dev->mode_config.max_width = MGAG200_MAX_FB_WIDTH; > @@ -1632,9 +1637,10 @@ int mgag200_modeset_init(struct mga_device *mdev) > } > encoder->possible_crtcs = 0x1; > > - connector = mga_vga_init(mdev->dev); > - if (!connector) { > - DRM_ERROR("mga_vga_init failed\n"); > + ret = mgag200_vga_connector_init(mdev); > + if (ret) { > + drm_err(mdev->dev, > + "mga_vga_connector_init() failed, error %d\n", ret); s/mga_vga_connector_init/mgag200_vga_connector_init/ > return -1; > } > > -- > 2.26.0 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [PATCH 02/17] drm/mgag200: Remove unused fields from struct mga_device
On Wed, Apr 29, 2020 at 04:32:23PM +0200, Thomas Zimmermann wrote: > The fields mode_info, num_crtcs and mode in struct mga_device serve > no purpose. Remove them. > > Signed-off-by: Thomas Zimmermann Looks straight forward. Acked-by: Sam Ravnborg > --- > drivers/gpu/drm/mgag200/mgag200_drv.h | 8 > drivers/gpu/drm/mgag200/mgag200_main.c | 3 --- > drivers/gpu/drm/mgag200/mgag200_mode.c | 6 -- > 3 files changed, 17 deletions(-) > > diff --git a/drivers/gpu/drm/mgag200/mgag200_drv.h > b/drivers/gpu/drm/mgag200/mgag200_drv.h > index c7f2000d46fce..de3181bd63ca0 100644 > --- a/drivers/gpu/drm/mgag200/mgag200_drv.h > +++ b/drivers/gpu/drm/mgag200/mgag200_drv.h > @@ -104,11 +104,6 @@ struct mga_crtc { > bool enabled; > }; > > -struct mga_mode_info { > - bool mode_config_initialized; > - struct mga_crtc *crtc; > -}; > - > struct mga_i2c_chan { > struct i2c_adapter adapter; > struct drm_device *dev; > @@ -155,15 +150,12 @@ struct mga_device { > void __iomem*rmmio; > > struct mga_mc mc; > - struct mga_mode_infomode_info; > > size_t vram_fb_available; > > boolsuspended; > - int num_crtc; > enum mga_type type; > int has_sdram; > - struct drm_display_mode mode; > > int bpp_shifts[4]; > > diff --git a/drivers/gpu/drm/mgag200/mgag200_main.c > b/drivers/gpu/drm/mgag200/mgag200_main.c > index 46cc32816f1e1..698fbf31337d4 100644 > --- a/drivers/gpu/drm/mgag200/mgag200_main.c > +++ b/drivers/gpu/drm/mgag200/mgag200_main.c > @@ -98,9 +98,6 @@ static int mgag200_device_init(struct drm_device *dev, > mdev->flags = mgag200_flags_from_driver_data(flags); > mdev->type = mgag200_type_from_driver_data(flags); > > - /* Hardcode the number of CRTCs to 1 */ > - mdev->num_crtc = 1; > - > pci_read_config_dword(dev->pdev, PCI_MGA_OPTION, ); > mdev->has_sdram = !(option & (1 << 14)); > > diff --git a/drivers/gpu/drm/mgag200/mgag200_mode.c > b/drivers/gpu/drm/mgag200/mgag200_mode.c > index c9d120b019649..ce41bebfdd1a2 100644 > --- a/drivers/gpu/drm/mgag200/mgag200_mode.c > +++ b/drivers/gpu/drm/mgag200/mgag200_mode.c > @@ -1135,9 +1135,6 @@ static int mga_crtc_mode_set(struct drm_crtc *crtc, > > WREG8(MGA_MISC_OUT, misc); > > - if (adjusted_mode) > - memcpy(>mode, mode, sizeof(struct drm_display_mode)); > - > mga_crtc_do_set_base(crtc, old_fb, x, y, 0); > > /* reset tagfifo */ > @@ -1443,7 +1440,6 @@ static void mga_crtc_init(struct mga_device *mdev) > drm_crtc_init(mdev->dev, _crtc->base, _crtc_funcs); > > drm_mode_crtc_set_gamma_size(_crtc->base, MGAG200_LUT_SIZE); > - mdev->mode_info.crtc = mga_crtc; > > drm_crtc_helper_add(_crtc->base, _helper_funcs); > } > @@ -1619,8 +1615,6 @@ int mgag200_modeset_init(struct mga_device *mdev) > struct drm_connector *connector; > int ret; > > - mdev->mode_info.mode_config_initialized = true; > - > mdev->dev->mode_config.max_width = MGAG200_MAX_FB_WIDTH; > mdev->dev->mode_config.max_height = MGAG200_MAX_FB_HEIGHT; > > -- > 2.26.0 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [PATCH] drm: enable render nodes wherever buffer sharing is supported
On Wed, Apr 29, 2020 at 09:51:19AM -0700, Peter Collingbourne wrote: > On Wed, Apr 29, 2020 at 9:17 AM Brian Starkey wrote: > > > > Hi Peter, > > > > On Mon, Apr 27, 2020 at 01:05:13PM -0700, Peter Collingbourne wrote: > > > Render nodes are not just useful for devices supporting GPU hardware > > > acceleration. Even on devices that only support dumb frame buffers, > > > they are useful in situations where composition (using software > > > rasterization) and KMS are done in different processes with buffer > > > sharing being used to send frame buffers between them. This is the > > > situation on Android, where surfaceflinger is the compositor and the > > > composer HAL uses KMS to display the buffers. Thus it is beneficial > > > to expose render nodes on all devices that support buffer sharing. > > > > If I understand your problem right, the issue is that you're getting > > your buffers in minigbm via pl111, which means you want a render node > > just for buffer allocation? Then HWComposer will import those on the > > primary node for displaying. > > Correct. > > > I'm not at all familiar with how minigbm sits in Android, but on our > > platforms where the Display and GPU devices are different, we allocate > > via ion in Gralloc, and import those into both the GPU and Display. > > I think that should work on pl111 too - if you can allocate contiguous > > memory from ion (or dma-buf heaps) in minigbm, then you don't need the > > render node. > > Those contiguous memory regions would not necessarily be compatible > with the pl111 device as far as I know -- according to [1], on some > devices, a designated memory region must be used for the framebuffer > and therefore the memory region allocated in CMA would not be > compatible. That being said, FVP doesn't appear to be one of those > devices, so in principle that might work for FVP (provided that the > user provides a sufficiently large cma=X kernel command line > argument), but not for those other devices. We have been doing that with mali-dp drivers for years. Because most of our dev environments are on FPGAs, we needed to use the local RAM on those boards so we've had to assign a memory region to the driver that in turn was using CMA. We've made heavy use of 'reserved-memory' and 'memory-region' nodes in the DT to link the two together, but things worked out quite well. Because the 'reserved-memory' sub-node was marked as 'compatible="shared-dma-pool"', gralloc and ION could be used to allocate memory from it. Best regards, Liviu > > Peter > > [1] > https://www.kernel.org/doc/Documentation/devicetree/bindings/display/arm%2Cpl11x.txt -- | I would like to | | fix the world, | | but they're not | | giving me the | \ source code! / --- ¯\_(ツ)_/¯ ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [PATCH v2] drm: Fix HDCP failures when SRM fw is missing
On 2020-04-29 at 10:46:29 -0400, Sean Paul wrote: > On Wed, Apr 29, 2020 at 10:22 AM Ramalingam C wrote: > > > > On 2020-04-29 at 09:58:16 -0400, Sean Paul wrote: > > > On Wed, Apr 29, 2020 at 9:50 AM Ramalingam C > > > wrote: > > > > > > > > On 2020-04-14 at 15:02:55 -0400, Sean Paul wrote: > > > > > From: Sean Paul > > > > > > > > > > The SRM cleanup in 79643fddd6eb2 ("drm/hdcp: optimizing the srm > > > > > handling") inadvertently altered the behavior of HDCP auth when > > > > > the SRM firmware is missing. Before that patch, missing SRM was > > > > > interpreted as the device having no revoked keys. With that patch, > > > > > if the SRM fw file is missing we reject _all_ keys. > > > > > > > > > > This patch fixes that regression by returning success if the file > > > > > cannot be found. It also checks the return value from request_srm such > > > > > that we won't end up trying to parse the ksv list if there is an error > > > > > fetching it. > > > > > > > > > > Fixes: 79643fddd6eb ("drm/hdcp: optimizing the srm handling") > > > > > Cc: sta...@vger.kernel.org > > > > > Cc: Ramalingam C > > > > > Cc: Sean Paul > > > > > Cc: Maarten Lankhorst > > > > > Cc: Maxime Ripard > > > > > Cc: Thomas Zimmermann > > > > > Cc: David Airlie > > > > > Cc: Daniel Vetter > > > > > Cc: dri-devel@lists.freedesktop.org > > > > > Signed-off-by: Sean Paul > > > > > > > > > > Changes in v2: > > > > > -Noticed a couple other things to clean up > > > > > --- > > > > > > > > > > Sorry for the quick rev, noticed a couple other loose ends that should > > > > > be cleaned up. > > > > > > > > > > drivers/gpu/drm/drm_hdcp.c | 8 +++- > > > > > 1 file changed, 7 insertions(+), 1 deletion(-) > > > > > > > > > > diff --git a/drivers/gpu/drm/drm_hdcp.c b/drivers/gpu/drm/drm_hdcp.c > > > > > index 7f386adcf872..910108ccaae1 100644 > > > > > --- a/drivers/gpu/drm/drm_hdcp.c > > > > > +++ b/drivers/gpu/drm/drm_hdcp.c > > > > > @@ -241,8 +241,12 @@ static int drm_hdcp_request_srm(struct > > > > > drm_device *drm_dev, > > > > > > > > > > ret = request_firmware_direct(, (const char *)fw_name, > > > > > drm_dev->dev); > > > > > - if (ret < 0) > > > > > + if (ret < 0) { > > > > > + *revoked_ksv_cnt = 0; > > > > > + *revoked_ksv_list = NULL; > > > > These two variables are already initialized by the caller. > > > > > > Right now it is, but that's not guaranteed. In the ret == 0 case, it's > > > pretty common for a caller to assume the called function has > > > validated/assigned all the function output. > > Ok. > > > > > > > > + ret = 0; > > > > Missing of this should have been caught by CI. May be CI system always > > > > having the SRM file from previous execution. Never been removed. IGT > > > > need a fix to clean the prior SRM files before execution. > > > > > > > > CI fix shouldn't block this fix. > > > > > goto exit; > > > > > + } > > > > > > > > > > if (fw->size && fw->data) > > > > > ret = drm_hdcp_srm_update(fw->data, fw->size, > > > > > revoked_ksv_list, > > > > > @@ -287,6 +291,8 @@ int drm_hdcp_check_ksvs_revoked(struct drm_device > > > > > *drm_dev, u8 *ksvs, > > > > > > > > > > ret = drm_hdcp_request_srm(drm_dev, _ksv_list, > > > > > _ksv_cnt); > > > > > + if (ret) > > > > > + return ret; > > > > This error code also shouldn't effect the caller(i915) > > > > > > Why not? I'd assume an invalid SRM revocation list should probably be > > > treated as failure? > > IMHO invalid SRM revocation need not be treated as HDCP authentication > > failure. > > > > First of all SRM need not supplied by all players. and incase, supplied > > SRM is not as per the spec, then we dont have any list of revoked ID. > > with this I dont think we need to fail the HDCP authentication. Until we > > have valid list of revoked IDs from SRM, and the receiver ID is matching > > to one of the revoked IDs, I wouldn't want to fail the HDCP > > authentication. > > > > Ok, thanks for the explanation. This all seems reasonable to me. > > Looks like this can be applied as-is, right? Yes. Thanks, Ram > I'll review the patch you > posted so we can ignore the -ve return values. > > Thanks for the review! > > Sean > > > -Ram > > > > > > > > > > hence pushed a > > > > change https://patchwork.freedesktop.org/series/76730/ > > > > > > > > With these addresed. > > > > > > > > LGTM. > > > > > > > > Reviewed-by: Ramalingam C > > > > > > > > > > /* revoked_ksv_cnt will be zero when above function failed */ > > > > > for (i = 0; i < revoked_ksv_cnt; i++) > > > > > -- > > > > > Sean Paul, Software Engineer, Google / Chromium OS > > > > > ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [PATCH] drm: enable render nodes wherever buffer sharing is supported
Hi Peter, On Mon, Apr 27, 2020 at 01:05:13PM -0700, Peter Collingbourne wrote: > Render nodes are not just useful for devices supporting GPU hardware > acceleration. Even on devices that only support dumb frame buffers, > they are useful in situations where composition (using software > rasterization) and KMS are done in different processes with buffer > sharing being used to send frame buffers between them. This is the > situation on Android, where surfaceflinger is the compositor and the > composer HAL uses KMS to display the buffers. Thus it is beneficial > to expose render nodes on all devices that support buffer sharing. If I understand your problem right, the issue is that you're getting your buffers in minigbm via pl111, which means you want a render node just for buffer allocation? Then HWComposer will import those on the primary node for displaying. I'm not at all familiar with how minigbm sits in Android, but on our platforms where the Display and GPU devices are different, we allocate via ion in Gralloc, and import those into both the GPU and Display. I think that should work on pl111 too - if you can allocate contiguous memory from ion (or dma-buf heaps) in minigbm, then you don't need the render node. Cheers, -Brian ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [PATCH] drm/amdgpu/smu10: remove duplicate assignment of smu10_hwmgr_funcs members
On Tue, Apr 28, 2020 at 8:47 AM Jason Yan wrote: > > The struct member 'asic_setup' was assigned twice, let's remove one: > > static const struct pp_hwmgr_func smu10_hwmgr_funcs = { > .. > .asic_setup = NULL, > .. > .asic_setup = smu10_setup_asic_task, > .. > }; > > This fixes the following coccicheck warning: > > drivers/gpu/drm/amd/powerplay/hwmgr/smu10_hwmgr.c:1357:52-53: > asic_setup: first occurrence line 1360, second occurrence line 1388 > > Signed-off-by: Jason Yan Applied. Thanks! Alex > --- > drivers/gpu/drm/amd/powerplay/hwmgr/smu10_hwmgr.c | 1 - > 1 file changed, 1 deletion(-) > > diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/smu10_hwmgr.c > b/drivers/gpu/drm/amd/powerplay/hwmgr/smu10_hwmgr.c > index 1cc30f750c26..4f8c1b85e688 100644 > --- a/drivers/gpu/drm/amd/powerplay/hwmgr/smu10_hwmgr.c > +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/smu10_hwmgr.c > @@ -1357,7 +1357,6 @@ static int smu10_asic_reset(struct pp_hwmgr *hwmgr, > enum SMU_ASIC_RESET_MODE mod > static const struct pp_hwmgr_func smu10_hwmgr_funcs = { > .backend_init = smu10_hwmgr_backend_init, > .backend_fini = smu10_hwmgr_backend_fini, > - .asic_setup = NULL, > .apply_state_adjust_rules = smu10_apply_state_adjust_rules, > .force_dpm_level = smu10_dpm_force_dpm_level, > .get_power_state_size = smu10_get_power_state_size, > -- > 2.21.1 > > ___ > dri-devel mailing list > dri-devel@lists.freedesktop.org > https://lists.freedesktop.org/mailman/listinfo/dri-devel ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [PATCH] drm/amd/display: remove duplicate assignment of dcn21_funcs members
On Tue, Apr 28, 2020 at 8:46 AM Jason Yan wrote: > > Fix the following coccicheck warning: > > drivers/gpu/drm/amd/display/dc/dcn21/dcn21_init.c:31:51-52: > exit_optimized_pwr_state: first occurrence line 86, second occurrence > line 92 > drivers/gpu/drm/amd/display/dc/dcn21/dcn21_init.c:31:51-52: > optimize_pwr_state: first occurrence line 85, second occurrence line 91 > drivers/gpu/drm/amd/display/dc/dcn21/dcn21_init.c:31:51-52: > set_cursor_attribute: first occurrence line 71, second occurrence line > 89 > drivers/gpu/drm/amd/display/dc/dcn21/dcn21_init.c:31:51-52: > set_cursor_position: first occurrence line 70, second occurrence line 88 > drivers/gpu/drm/amd/display/dc/dcn21/dcn21_init.c:31:51-52: > set_cursor_sdr_white_level: first occurrence line 72, second occurrence > line 90 > > Signed-off-by: Jason Yan Applied. Thanks! Alex > --- > drivers/gpu/drm/amd/display/dc/dcn21/dcn21_init.c | 5 - > 1 file changed, 5 deletions(-) > > diff --git a/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_init.c > b/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_init.c > index 8410a6305a9a..fe64bcb49456 100644 > --- a/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_init.c > +++ b/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_init.c > @@ -85,11 +85,6 @@ static const struct hw_sequencer_funcs dcn21_funcs = { > .optimize_pwr_state = dcn21_optimize_pwr_state, > .exit_optimized_pwr_state = dcn21_exit_optimized_pwr_state, > .get_vupdate_offset_from_vsync = dcn10_get_vupdate_offset_from_vsync, > - .set_cursor_position = dcn10_set_cursor_position, > - .set_cursor_attribute = dcn10_set_cursor_attribute, > - .set_cursor_sdr_white_level = dcn10_set_cursor_sdr_white_level, > - .optimize_pwr_state = dcn21_optimize_pwr_state, > - .exit_optimized_pwr_state = dcn21_exit_optimized_pwr_state, > .power_down = dce110_power_down, > }; > > -- > 2.21.1 > > ___ > dri-devel mailing list > dri-devel@lists.freedesktop.org > https://lists.freedesktop.org/mailman/listinfo/dri-devel ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
RE: [PATCH 03/17] drm/mgag200: Embed connector instance in struct mga_device
>-Original Message- >From: dri-devel On Behalf Of >Thomas Zimmermann >Sent: Wednesday, April 29, 2020 10:32 AM >To: airl...@redhat.com; dan...@ffwll.ch; kra...@redhat.com; >nor...@tronnes.org; s...@ravnborg.org; john.p.donne...@oracle.com >Cc: Thomas Zimmermann ; dri- >de...@lists.freedesktop.org >Subject: [PATCH 03/17] drm/mgag200: Embed connector instance in struct >mga_device > >Storing the connector instance in struct mga_device avoids some >dynamic memory allocation. Done im preparation of converting s/im/in/ You might also want to comment that you clean up the i2c info on error. Straight forward replacement of pointer with an embedded data structure: Reviewed-by: Michael J. Ruhl M >mgag200 to simple-KMS helpers. > >Signed-off-by: Thomas Zimmermann >--- > drivers/gpu/drm/mgag200/mgag200_drv.h | 1 + > drivers/gpu/drm/mgag200/mgag200_mode.c | 54 ++--- >- > 2 files changed, 31 insertions(+), 24 deletions(-) > >diff --git a/drivers/gpu/drm/mgag200/mgag200_drv.h >b/drivers/gpu/drm/mgag200/mgag200_drv.h >index de3181bd63ca0..09b43a0ff6bbf 100644 >--- a/drivers/gpu/drm/mgag200/mgag200_drv.h >+++ b/drivers/gpu/drm/mgag200/mgag200_drv.h >@@ -164,6 +164,7 @@ struct mga_device { > /* SE model number stored in reg 0x1e24 */ > u32 unique_rev_id; > >+ struct mga_connector connector; > struct drm_encoder encoder; > }; > >diff --git a/drivers/gpu/drm/mgag200/mgag200_mode.c >b/drivers/gpu/drm/mgag200/mgag200_mode.c >index ce41bebfdd1a2..eaa3fca7216ac 100644 >--- a/drivers/gpu/drm/mgag200/mgag200_mode.c >+++ b/drivers/gpu/drm/mgag200/mgag200_mode.c >@@ -1444,6 +1444,10 @@ static void mga_crtc_init(struct mga_device >*mdev) > drm_crtc_helper_add(_crtc->base, _helper_funcs); > } > >+/* >+ * Connector >+ */ >+ > static int mga_vga_get_modes(struct drm_connector *connector) > { > struct mga_connector *mga_connector = >to_mga_connector(connector); >@@ -1568,7 +1572,6 @@ static void mga_connector_destroy(struct >drm_connector *connector) > struct mga_connector *mga_connector = >to_mga_connector(connector); > mgag200_i2c_destroy(mga_connector->i2c); > drm_connector_cleanup(connector); >- kfree(connector); > } > > static const struct drm_connector_helper_funcs >mga_vga_connector_helper_funcs = { >@@ -1582,37 +1585,39 @@ static const struct drm_connector_funcs >mga_vga_connector_funcs = { > .destroy = mga_connector_destroy, > }; > >-static struct drm_connector *mga_vga_init(struct drm_device *dev) >+static int mgag200_vga_connector_init(struct mga_device *mdev) > { >- struct drm_connector *connector; >- struct mga_connector *mga_connector; >- >- mga_connector = kzalloc(sizeof(struct mga_connector), >GFP_KERNEL); >- if (!mga_connector) >- return NULL; >- >- connector = _connector->base; >- mga_connector->i2c = mgag200_i2c_create(dev); >- if (!mga_connector->i2c) >- DRM_ERROR("failed to add ddc bus\n"); >+ struct drm_device *dev = mdev->dev; >+ struct mga_connector *mconnector = >connector; >+ struct drm_connector *connector = >base; >+ struct mga_i2c_chan *i2c; >+ int ret; > >- drm_connector_init_with_ddc(dev, connector, >- _vga_connector_funcs, >- DRM_MODE_CONNECTOR_VGA, >- _connector->i2c->adapter); >+ i2c = mgag200_i2c_create(dev); >+ if (!i2c) >+ drm_warn(dev, "failed to add DDC bus\n"); > >+ ret = drm_connector_init_with_ddc(dev, connector, >+_vga_connector_funcs, >+DRM_MODE_CONNECTOR_VGA, >+>adapter); >+ if (ret) >+ goto err_mgag200_i2c_destroy; > drm_connector_helper_add(connector, >_vga_connector_helper_funcs); > >- drm_connector_register(connector); >+ mconnector->i2c = i2c; > >- return connector; >-} >+ return 0; > >+err_mgag200_i2c_destroy: >+ mgag200_i2c_destroy(i2c); >+ return ret; >+} > > int mgag200_modeset_init(struct mga_device *mdev) > { > struct drm_encoder *encoder = >encoder; >- struct drm_connector *connector; >+ struct drm_connector *connector = >connector.base; > int ret; > > mdev->dev->mode_config.max_width = >MGAG200_MAX_FB_WIDTH; >@@ -1632,9 +1637,10 @@ int mgag200_modeset_init(struct mga_device >*mdev) > } > encoder->possible_crtcs = 0x1; > >- connector = mga_vga_init(mdev->dev); >- if (!connector) { >- DRM_ERROR("mga_vga_init failed\n"); >+ ret = mgag200_vga_connector_init(mdev); >+ if (ret) { >+ drm_err(mdev->dev, >+ "mga_vga_connector_init() failed, error %d\n", ret); > return -1; > } > >-- >2.26.0 > >___ >dri-devel mailing list
Re: [PATCH] drm/ast: remove duplicate assignment of ast_crtc_funcs member
Hi Am 29.04.20 um 16:10 schrieb Jason Yan: > The struct member 'set_config' was assigned twice: > > static const struct drm_crtc_funcs ast_crtc_funcs = { > .reset = ast_crtc_reset, > .set_config = drm_crtc_helper_set_config, > .. > .set_config = drm_atomic_helper_set_config, > .. > }; > > Since the second one is which we use now in fact, we can remove the > first one. > > This fixes the following coccicheck warning: > > drivers/gpu/drm/ast/ast_mode.c:932:50-51: set_config: first occurrence > line 934, second occurrence line 937 > > Signed-off-by: Jason Yan Reviewed-by: Thomas Zimmermann Thanks! I'll apply the patch to drm-misc-next soonish. Best regards Thomas > --- > drivers/gpu/drm/ast/ast_mode.c | 1 - > 1 file changed, 1 deletion(-) > > diff --git a/drivers/gpu/drm/ast/ast_mode.c b/drivers/gpu/drm/ast/ast_mode.c > index d2ab81f9c498..7062bcd78740 100644 > --- a/drivers/gpu/drm/ast/ast_mode.c > +++ b/drivers/gpu/drm/ast/ast_mode.c > @@ -931,7 +931,6 @@ static void ast_crtc_atomic_destroy_state(struct drm_crtc > *crtc, > > static const struct drm_crtc_funcs ast_crtc_funcs = { > .reset = ast_crtc_reset, > - .set_config = drm_crtc_helper_set_config, > .gamma_set = drm_atomic_helper_legacy_gamma_set, > .destroy = ast_crtc_destroy, > .set_config = drm_atomic_helper_set_config, > -- Thomas Zimmermann Graphics Driver Developer SUSE Software Solutions Germany GmbH Maxfeldstr. 5, 90409 Nürnberg, Germany (HRB 36809, AG Nürnberg) Geschäftsführer: Felix Imendörffer signature.asc Description: OpenPGP digital signature ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [PATCH] drm/i915/hdcp: Fix the return handling of drm_hdcp_check_ksvs_revoked
On Wed, Apr 29, 2020 at 9:46 AM Ramalingam C wrote: > > drm_hdcp_check_ksvs_revoked() returns the number of revoked keys and > error codes when the SRM parsing is failed. > > Errors in SRM parsing can't affect the HDCP auth, hence with this patch, > I915 will look out for revoked key count alone. > Reviewed-by: Sean Paul > Signed-off-by: Ramalingam C > cc: Sean Paul > --- > drivers/gpu/drm/i915/display/intel_hdcp.c | 8 > 1 file changed, 4 insertions(+), 4 deletions(-) > > diff --git a/drivers/gpu/drm/i915/display/intel_hdcp.c > b/drivers/gpu/drm/i915/display/intel_hdcp.c > index 2cbc4619b4ce..96bf6def9830 100644 > --- a/drivers/gpu/drm/i915/display/intel_hdcp.c > +++ b/drivers/gpu/drm/i915/display/intel_hdcp.c > @@ -576,7 +576,7 @@ int intel_hdcp_auth_downstream(struct intel_connector > *connector) > goto err; > > if (drm_hdcp_check_ksvs_revoked(_priv->drm, ksv_fifo, > - num_downstream)) { > + num_downstream) > 0) { > drm_err(_priv->drm, "Revoked Ksv(s) in ksv_fifo\n"); > ret = -EPERM; > goto err; > @@ -682,7 +682,7 @@ static int intel_hdcp_auth(struct intel_connector > *connector) > if (ret < 0) > return ret; > > - if (drm_hdcp_check_ksvs_revoked(_priv->drm, bksv.shim, 1)) { > + if (drm_hdcp_check_ksvs_revoked(_priv->drm, bksv.shim, 1) > 0) { > drm_err(_priv->drm, "BKSV is revoked\n"); > return -EPERM; > } > @@ -1283,7 +1283,7 @@ static int hdcp2_authentication_key_exchange(struct > intel_connector *connector) > > if (drm_hdcp_check_ksvs_revoked(_priv->drm, > msgs.send_cert.cert_rx.receiver_id, > - 1)) { > + 1) > 0) { > drm_err(_priv->drm, "Receiver ID is revoked\n"); > return -EPERM; > } > @@ -1484,7 +1484,7 @@ int hdcp2_authenticate_repeater_topology(struct > intel_connector *connector) > HDCP_2_2_DEV_COUNT_LO(rx_info[1])); > if (drm_hdcp_check_ksvs_revoked(_priv->drm, > msgs.recvid_list.receiver_ids, > - device_cnt)) { > + device_cnt) > 0) { > drm_err(_priv->drm, "Revoked receiver ID(s) is in > list\n"); > return -EPERM; > } > -- > 2.20.1 > > ___ > dri-devel mailing list > dri-devel@lists.freedesktop.org > https://lists.freedesktop.org/mailman/listinfo/dri-devel ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [PATCH v2] drm: Fix HDCP failures when SRM fw is missing
On Wed, Apr 29, 2020 at 10:22 AM Ramalingam C wrote: > > On 2020-04-29 at 09:58:16 -0400, Sean Paul wrote: > > On Wed, Apr 29, 2020 at 9:50 AM Ramalingam C wrote: > > > > > > On 2020-04-14 at 15:02:55 -0400, Sean Paul wrote: > > > > From: Sean Paul > > > > > > > > The SRM cleanup in 79643fddd6eb2 ("drm/hdcp: optimizing the srm > > > > handling") inadvertently altered the behavior of HDCP auth when > > > > the SRM firmware is missing. Before that patch, missing SRM was > > > > interpreted as the device having no revoked keys. With that patch, > > > > if the SRM fw file is missing we reject _all_ keys. > > > > > > > > This patch fixes that regression by returning success if the file > > > > cannot be found. It also checks the return value from request_srm such > > > > that we won't end up trying to parse the ksv list if there is an error > > > > fetching it. > > > > > > > > Fixes: 79643fddd6eb ("drm/hdcp: optimizing the srm handling") > > > > Cc: sta...@vger.kernel.org > > > > Cc: Ramalingam C > > > > Cc: Sean Paul > > > > Cc: Maarten Lankhorst > > > > Cc: Maxime Ripard > > > > Cc: Thomas Zimmermann > > > > Cc: David Airlie > > > > Cc: Daniel Vetter > > > > Cc: dri-devel@lists.freedesktop.org > > > > Signed-off-by: Sean Paul > > > > > > > > Changes in v2: > > > > -Noticed a couple other things to clean up > > > > --- > > > > > > > > Sorry for the quick rev, noticed a couple other loose ends that should > > > > be cleaned up. > > > > > > > > drivers/gpu/drm/drm_hdcp.c | 8 +++- > > > > 1 file changed, 7 insertions(+), 1 deletion(-) > > > > > > > > diff --git a/drivers/gpu/drm/drm_hdcp.c b/drivers/gpu/drm/drm_hdcp.c > > > > index 7f386adcf872..910108ccaae1 100644 > > > > --- a/drivers/gpu/drm/drm_hdcp.c > > > > +++ b/drivers/gpu/drm/drm_hdcp.c > > > > @@ -241,8 +241,12 @@ static int drm_hdcp_request_srm(struct drm_device > > > > *drm_dev, > > > > > > > > ret = request_firmware_direct(, (const char *)fw_name, > > > > drm_dev->dev); > > > > - if (ret < 0) > > > > + if (ret < 0) { > > > > + *revoked_ksv_cnt = 0; > > > > + *revoked_ksv_list = NULL; > > > These two variables are already initialized by the caller. > > > > Right now it is, but that's not guaranteed. In the ret == 0 case, it's > > pretty common for a caller to assume the called function has > > validated/assigned all the function output. > Ok. > > > > > > + ret = 0; > > > Missing of this should have been caught by CI. May be CI system always > > > having the SRM file from previous execution. Never been removed. IGT > > > need a fix to clean the prior SRM files before execution. > > > > > > CI fix shouldn't block this fix. > > > > goto exit; > > > > + } > > > > > > > > if (fw->size && fw->data) > > > > ret = drm_hdcp_srm_update(fw->data, fw->size, > > > > revoked_ksv_list, > > > > @@ -287,6 +291,8 @@ int drm_hdcp_check_ksvs_revoked(struct drm_device > > > > *drm_dev, u8 *ksvs, > > > > > > > > ret = drm_hdcp_request_srm(drm_dev, _ksv_list, > > > > _ksv_cnt); > > > > + if (ret) > > > > + return ret; > > > This error code also shouldn't effect the caller(i915) > > > > Why not? I'd assume an invalid SRM revocation list should probably be > > treated as failure? > IMHO invalid SRM revocation need not be treated as HDCP authentication > failure. > > First of all SRM need not supplied by all players. and incase, supplied > SRM is not as per the spec, then we dont have any list of revoked ID. > with this I dont think we need to fail the HDCP authentication. Until we > have valid list of revoked IDs from SRM, and the receiver ID is matching > to one of the revoked IDs, I wouldn't want to fail the HDCP > authentication. > Ok, thanks for the explanation. This all seems reasonable to me. Looks like this can be applied as-is, right? I'll review the patch you posted so we can ignore the -ve return values. Thanks for the review! Sean > -Ram > > > > > > > hence pushed a > > > change https://patchwork.freedesktop.org/series/76730/ > > > > > > With these addresed. > > > > > > LGTM. > > > > > > Reviewed-by: Ramalingam C > > > > > > > > /* revoked_ksv_cnt will be zero when above function failed */ > > > > for (i = 0; i < revoked_ksv_cnt; i++) > > > > -- > > > > Sean Paul, Software Engineer, Google / Chromium OS > > > > ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH 10/17] drm/mgag200: Set pitch in a separate helper function
The framebuffer's pitch is now set in mgag200_set_offset(). Signed-off-by: Thomas Zimmermann --- drivers/gpu/drm/mgag200/mgag200_mode.c | 41 +- 1 file changed, 27 insertions(+), 14 deletions(-) diff --git a/drivers/gpu/drm/mgag200/mgag200_mode.c b/drivers/gpu/drm/mgag200/mgag200_mode.c index 92dee31f16c42..eb83e471d72fc 100644 --- a/drivers/gpu/drm/mgag200/mgag200_mode.c +++ b/drivers/gpu/drm/mgag200/mgag200_mode.c @@ -1003,6 +1003,32 @@ static void mgag200_set_mode_regs(struct mga_device *mdev, mga_crtc_set_plls(mdev, mode->clock); } +static void mgag200_set_offset(struct mga_device *mdev, + const struct drm_framebuffer *fb) +{ + unsigned int offset; + uint8_t crtc13, crtcext0; + u8 bppshift; + + bppshift = mdev->bpp_shifts[fb->format->cpp[0] - 1]; + + offset = fb->pitches[0] / fb->format->cpp[0]; + if (fb->format->cpp[0] * 8 == 24) + offset = (offset * 3) >> (4 - bppshift); + else + offset = offset >> (4 - bppshift); + + RREG_ECRT(0, crtcext0); + + crtc13 = offset & 0xff; + + crtcext0 &= ~GENMASK(5, 4); + crtcext0 |= (offset & GENMASK(9, 8)) >> 4; + + WREG_CRT(0x13, crtc13); + WREG_ECRT(0x00, crtcext0); +} + static int mga_crtc_mode_set(struct drm_crtc *crtc, struct drm_display_mode *mode, struct drm_display_mode *adjusted_mode, @@ -1011,7 +1037,6 @@ static int mga_crtc_mode_set(struct drm_crtc *crtc, struct drm_device *dev = crtc->dev; struct mga_device *mdev = dev->dev_private; const struct drm_framebuffer *fb = crtc->primary->fb; - int pitch; int option = 0, option2 = 0; int i; unsigned char misc = 0; @@ -1122,12 +1147,6 @@ static int mga_crtc_mode_set(struct drm_crtc *crtc, WREG_SEQ(3, 0); WREG_SEQ(4, 0xe); - pitch = fb->pitches[0] / fb->format->cpp[0]; - if (fb->format->cpp[0] * 8 == 24) - pitch = (pitch * 3) >> (4 - bppshift); - else - pitch = pitch >> (4 - bppshift); - WREG_GFX(0, 0); WREG_GFX(1, 0); WREG_GFX(2, 0); @@ -1144,20 +1163,15 @@ static int mga_crtc_mode_set(struct drm_crtc *crtc, WREG_CRT(13, 0); WREG_CRT(14, 0); WREG_CRT(15, 0); - WREG_CRT(19, pitch & 0xFF); - - ext_vga[0] = 0; /* TODO interlace */ - ext_vga[0] |= (pitch & 0x300) >> 4; if (fb->format->cpp[0] * 8 == 24) ext_vga[3] = (((1 << bppshift) * 3) - 1) | 0x80; else ext_vga[3] = ((1 << bppshift) - 1) | 0x80; ext_vga[4] = 0; - WREG_ECRT(0, ext_vga[0]); WREG_ECRT(3, ext_vga[3]); WREG_ECRT(4, ext_vga[4]); @@ -1171,8 +1185,6 @@ static int mga_crtc_mode_set(struct drm_crtc *crtc, WREG_ECRT(6, 0); } - WREG_ECRT(0, ext_vga[0]); - misc = RREG8(MGA_MISC_IN); misc |= MGAREG_MISC_IOADSEL | MGAREG_MISC_RAMMAPEN | @@ -1180,6 +1192,7 @@ static int mga_crtc_mode_set(struct drm_crtc *crtc, WREG8(MGA_MISC_OUT, misc); mga_crtc_do_set_base(mdev, fb, old_fb); + mgag200_set_offset(mdev, fb); mgag200_set_mode_regs(mdev, mode); -- 2.26.0 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH 15/17] drm/mgag200: Remove waiting from DPMS code
The mgag200 drivers waits for the VSYNC flag to get signalled (i.e., the page flip happens) before changing DPMS settings. This doesn't work reliably if no mode has been programmed. Therefore remove the waiting code. Synchronization with page flips should be done by DRM's vblank handlers anyway. Signed-off-by: Thomas Zimmermann --- drivers/gpu/drm/mgag200/mgag200_mode.c | 26 -- 1 file changed, 26 deletions(-) diff --git a/drivers/gpu/drm/mgag200/mgag200_mode.c b/drivers/gpu/drm/mgag200/mgag200_mode.c index ee1cbe5decd71..884fc668a6dae 100644 --- a/drivers/gpu/drm/mgag200/mgag200_mode.c +++ b/drivers/gpu/drm/mgag200/mgag200_mode.c @@ -75,30 +75,6 @@ static void mga_crtc_load_lut(struct drm_crtc *crtc) } } -static inline void mga_wait_vsync(struct mga_device *mdev) -{ - unsigned long timeout = jiffies + HZ/10; - unsigned int status = 0; - - do { - status = RREG32(MGAREG_Status); - } while ((status & 0x08) && time_before(jiffies, timeout)); - timeout = jiffies + HZ/10; - status = 0; - do { - status = RREG32(MGAREG_Status); - } while (!(status & 0x08) && time_before(jiffies, timeout)); -} - -static inline void mga_wait_busy(struct mga_device *mdev) -{ - unsigned long timeout = jiffies + HZ; - unsigned int status = 0; - do { - status = RREG8(MGAREG_Status + 2); - } while ((status & 0x01) && time_before(jiffies, timeout)); -} - #define P_ARRAY_SIZE 9 static int mga_g200se_set_plls(struct mga_device *mdev, long clock) @@ -1435,8 +1411,6 @@ static void mga_crtc_dpms(struct drm_crtc *crtc, int mode) #endif WREG8(MGAREG_SEQ_INDEX, 0x01); seq1 |= RREG8(MGAREG_SEQ_DATA) & ~0x20; - mga_wait_vsync(mdev); - mga_wait_busy(mdev); WREG8(MGAREG_SEQ_DATA, seq1); msleep(20); WREG8(MGAREG_CRTCEXT_INDEX, 0x01); -- 2.26.0 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH 00/17] drm/mgag200: Convert to atomic modesetting
This patchset converts mgag200 to atomic modesetting. It uses simple KMS helpers and SHMEM. Patches 1 to 4 simplifies the driver before the conversion. For example, the HW cursor is not usable with the way universal planes work. A few data structures can be cleaned up. Patches 5 to 15 untangle the existing modesetting code into smaller functions. Specifically, mode setting and plane updates are being separated from each other. Patch 16 converts mgag200 to simple KMS helpers and enables atomic mode setting. As some HW seems to require a framebuffer offset of 0 within the video memory, it does not work with atomic modesetting. Atomically switching plane framebuffers, requires either source or target buffer to be located at a non-0 offet. To resolve this problem, patch 17 converts mgag200 from VRAM helpers to SHMEM helpers. During plane updates, the content of the SHMEM BO is memcpy'd to VRAM. From my subjective obersation, performance is not nuch different from the original code. The patchset has been tested on MGA G200EH hardware. Thomas Zimmermann (17): drm/mgag200: Remove HW cursor drm/mgag200: Remove unused fields from struct mga_device drm/mgag200: Embed connector instance in struct mga_device drm/mgag200: Use managed mode-config initialization drm/mgag200: Clean up mga_set_start_address() drm/mgag200: Clean up mga_crtc_do_set_base() drm/mgag200: Move mode-setting code into separate helper function drm/mgag200: Split MISC register update into PLL selection, SYNC and I/O drm/mgag200: Update mode registers after plane registers drm/mgag200: Set pitch in a separate helper function drm/mgag200: Set primary plane's format in separate helper function drm/mgag200: Move TAGFIFO reset into separate function drm/mgag200: Move hiprilvl setting into separate functions drm/mgag200: Move register initialization into separate function drm/mgag200: Remove waiting from DPMS code drm/mgag200: Convert to simple KMS helper drm/mgag200: Replace VRAM helpers with SHMEM helpers drivers/gpu/drm/mgag200/Kconfig | 4 +- drivers/gpu/drm/mgag200/Makefile | 2 +- drivers/gpu/drm/mgag200/mgag200_cursor.c | 319 drivers/gpu/drm/mgag200/mgag200_drv.c| 51 +- drivers/gpu/drm/mgag200/mgag200_drv.h| 43 +- drivers/gpu/drm/mgag200/mgag200_main.c | 28 - drivers/gpu/drm/mgag200/mgag200_mode.c | 948 --- drivers/gpu/drm/mgag200/mgag200_reg.h| 5 +- drivers/gpu/drm/mgag200/mgag200_ttm.c| 35 +- 9 files changed, 563 insertions(+), 872 deletions(-) delete mode 100644 drivers/gpu/drm/mgag200/mgag200_cursor.c -- 2.26.0 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH 14/17] drm/mgag200: Move register initialization into separate function
Registers are initialized with constants. This is now done in mgag200_init_regs(), mgag200_set_dac_regs() and mgag200_set_pci_regs(). Later patches should move these calls from mode setting to device initialization. Signed-off-by: Thomas Zimmermann --- drivers/gpu/drm/mgag200/mgag200_mode.c | 262 ++--- 1 file changed, 148 insertions(+), 114 deletions(-) diff --git a/drivers/gpu/drm/mgag200/mgag200_mode.c b/drivers/gpu/drm/mgag200/mgag200_mode.c index a04404c5aa769..ee1cbe5decd71 100644 --- a/drivers/gpu/drm/mgag200/mgag200_mode.c +++ b/drivers/gpu/drm/mgag200/mgag200_mode.c @@ -919,6 +919,153 @@ static int mga_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y, return mga_crtc_do_set_base(mdev, fb, old_fb); } +static void mgag200_set_pci_regs(struct mga_device *mdev) +{ + uint32_t option = 0, option2 = 0; + struct drm_device *dev = mdev->dev; + + switch (mdev->type) { + case G200_SE_A: + case G200_SE_B: + if (mdev->has_sdram) + option = 0x40049120; + else + option = 0x4004d120; + option2 = 0x8000; + break; + case G200_WB: + case G200_EW3: + option = 0x41049120; + option2 = 0xb000; + break; + case G200_EV: + option = 0x0120; + option2 = 0xb000; + break; + case G200_EH: + case G200_EH3: + option = 0x0120; + option2 = 0xb000; + break; + case G200_ER: + break; + } + + if (option) + pci_write_config_dword(dev->pdev, PCI_MGA_OPTION, option); + + if (option2) + pci_write_config_dword(dev->pdev, PCI_MGA_OPTION2, option2); +} + +static void mgag200_set_dac_regs(struct mga_device *mdev) +{ + size_t i; + uint8_t dacvalue[] = { + /* 0x00: */0,0,0,0,0,0, 0x00,0, + /* 0x08: */0,0,0,0,0,0,0,0, + /* 0x10: */0,0,0,0,0,0,0,0, + /* 0x18: */ 0x00,0, 0xC9, 0xFF, 0xBF, 0x20, 0x1F, 0x20, + /* 0x20: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 0x28: */ 0x00, 0x00, 0x00, 0x00,0,0,0, 0x40, + /* 0x30: */ 0x00, 0xB0, 0x00, 0xC2, 0x34, 0x14, 0x02, 0x83, + /* 0x38: */ 0x00, 0x93, 0x00, 0x77, 0x00, 0x00, 0x00, 0x3A, + /* 0x40: */0,0,0,0,0,0,0,0, + /* 0x48: */0,0,0,0,0,0,0,0 + }; + + switch (mdev->type) { + case G200_SE_A: + case G200_SE_B: + dacvalue[MGA1064_VREF_CTL] = 0x03; + dacvalue[MGA1064_PIX_CLK_CTL] = MGA1064_PIX_CLK_CTL_SEL_PLL; + dacvalue[MGA1064_MISC_CTL] = MGA1064_MISC_CTL_DAC_EN | +MGA1064_MISC_CTL_VGA8 | +MGA1064_MISC_CTL_DAC_RAM_CS; + break; + case G200_WB: + case G200_EW3: + dacvalue[MGA1064_VREF_CTL] = 0x07; + break; + case G200_EV: + dacvalue[MGA1064_PIX_CLK_CTL] = MGA1064_PIX_CLK_CTL_SEL_PLL; + dacvalue[MGA1064_MISC_CTL] = MGA1064_MISC_CTL_VGA8 | +MGA1064_MISC_CTL_DAC_RAM_CS; + break; + case G200_EH: + case G200_EH3: + dacvalue[MGA1064_MISC_CTL] = MGA1064_MISC_CTL_VGA8 | +MGA1064_MISC_CTL_DAC_RAM_CS; + break; + case G200_ER: + break; + } + + for (i = 0; i < ARRAY_SIZE(dacvalue); i++) { + if ((i <= 0x17) || + (i == 0x1b) || + (i == 0x1c) || + ((i >= 0x1f) && (i <= 0x29)) || + ((i >= 0x30) && (i <= 0x37))) + continue; + if (IS_G200_SE(mdev) && + ((i == 0x2c) || (i == 0x2d) || (i == 0x2e))) + continue; + if ((mdev->type == G200_EV || + mdev->type == G200_WB || + mdev->type == G200_EH || + mdev->type == G200_EW3 || + mdev->type == G200_EH3) && + (i >= 0x44) && (i <= 0x4e)) + continue; + + WREG_DAC(i, dacvalue[i]); + } + + if (mdev->type == G200_ER) + WREG_DAC(0x90, 0); +} + +static void mgag200_init_regs(struct mga_device *mdev) +{ + uint8_t crtcext3, crtcext4; + uint8_t misc; + + mgag200_set_pci_regs(mdev); + mgag200_set_dac_regs(mdev); + + WREG_SEQ(2, 0x0f); + WREG_SEQ(3,
[PATCH 09/17] drm/mgag200: Update mode registers after plane registers
Setting the plane registers first and the mode registers afterwards reproduces the sequence used by atomic helpers. Done in preparation of switching to simple KMS helpers. Signed-off-by: Thomas Zimmermann --- drivers/gpu/drm/mgag200/mgag200_mode.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/mgag200/mgag200_mode.c b/drivers/gpu/drm/mgag200/mgag200_mode.c index b5bb02e9f05d6..92dee31f16c42 100644 --- a/drivers/gpu/drm/mgag200/mgag200_mode.c +++ b/drivers/gpu/drm/mgag200/mgag200_mode.c @@ -1146,8 +1146,6 @@ static int mga_crtc_mode_set(struct drm_crtc *crtc, WREG_CRT(15, 0); WREG_CRT(19, pitch & 0xFF); - mgag200_set_mode_regs(mdev, mode); - ext_vga[0] = 0; /* TODO interlace */ @@ -1183,6 +1181,8 @@ static int mga_crtc_mode_set(struct drm_crtc *crtc, mga_crtc_do_set_base(mdev, fb, old_fb); + mgag200_set_mode_regs(mdev, mode); + /* reset tagfifo */ if (mdev->type == G200_ER) { u32 mem_ctl = RREG32(MGAREG_MEMCTL); -- 2.26.0 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH 17/17] drm/mgag200: Replace VRAM helpers with SHMEM helpers
The VRAM helpers managed the framebuffer memory for mgag200. This came with several problems, as some MGA device require the scanout address to be located at VRAM offset 0. It's incompatible with the page-flip semantics of DRM's atomic modesettting. With atomic modesetting, old and new framebuffers have to be located in VRAM at the same time. So at least one of them has to reside at a non-0 offset. This patch replaces VRAM helpers with SHMEM helpers. GEM SHMEM buffers reside in system memory, and are shadow-copied into VRAM during page flips. The shadow copy always starts at VRAM offset 0. Signed-off-by: Thomas Zimmermann --- drivers/gpu/drm/mgag200/Kconfig| 4 +- drivers/gpu/drm/mgag200/mgag200_drv.c | 49 + drivers/gpu/drm/mgag200/mgag200_drv.h | 5 ++- drivers/gpu/drm/mgag200/mgag200_mode.c | 59 +++--- drivers/gpu/drm/mgag200/mgag200_ttm.c | 35 --- 5 files changed, 60 insertions(+), 92 deletions(-) diff --git a/drivers/gpu/drm/mgag200/Kconfig b/drivers/gpu/drm/mgag200/Kconfig index d60aa4b9ccd47..93be766715c9b 100644 --- a/drivers/gpu/drm/mgag200/Kconfig +++ b/drivers/gpu/drm/mgag200/Kconfig @@ -2,10 +2,8 @@ config DRM_MGAG200 tristate "Kernel modesetting driver for MGA G200 server engines" depends on DRM && PCI && MMU + select DRM_GEM_SHMEM_HELPER select DRM_KMS_HELPER - select DRM_VRAM_HELPER - select DRM_TTM - select DRM_TTM_HELPER help This is a KMS driver for the MGA G200 server chips, it does not support the original MGA G200 or any of the desktop diff --git a/drivers/gpu/drm/mgag200/mgag200_drv.c b/drivers/gpu/drm/mgag200/mgag200_drv.c index b1272165621ed..00ddea7d7d270 100644 --- a/drivers/gpu/drm/mgag200/mgag200_drv.c +++ b/drivers/gpu/drm/mgag200/mgag200_drv.c @@ -22,15 +22,11 @@ * which then performs further device association and calls our graphics init * functions */ -int mgag200_modeset = -1; +int mgag200_modeset = -1; MODULE_PARM_DESC(modeset, "Disable/Enable modesetting"); module_param_named(modeset, mgag200_modeset, int, 0400); -int mgag200_hw_bug_no_startadd = -1; -MODULE_PARM_DESC(modeset, "HW does not interpret scanout-buffer start address correctly"); -module_param_named(hw_bug_no_startadd, mgag200_hw_bug_no_startadd, int, 0400); - static struct drm_driver driver; static const struct pci_device_id pciidlist[] = { @@ -101,44 +97,6 @@ static void mga_pci_remove(struct pci_dev *pdev) DEFINE_DRM_GEM_FOPS(mgag200_driver_fops); -static bool mgag200_pin_bo_at_0(const struct mga_device *mdev) -{ - if (mgag200_hw_bug_no_startadd > 0) { - DRM_WARN_ONCE("Option hw_bug_no_startradd is enabled. Please " - "report the output of 'lspci -vvnn' to " - " if this " - "option is required to make mgag200 work " - "correctly on your system.\n"); - return true; - } else if (!mgag200_hw_bug_no_startadd) { - return false; - } - return mdev->flags & MGAG200_FLAG_HW_BUG_NO_STARTADD; -} - -int mgag200_driver_dumb_create(struct drm_file *file, - struct drm_device *dev, - struct drm_mode_create_dumb *args) -{ - struct mga_device *mdev = dev->dev_private; - unsigned long pg_align; - - if (WARN_ONCE(!dev->vram_mm, "VRAM MM not initialized")) - return -EINVAL; - - pg_align = 0ul; - - /* -* Aligning scanout buffers to the size of the video ram forces -* placement at offset 0. Works around a bug where HW does not -* respect 'startadd' field. -*/ - if (mgag200_pin_bo_at_0(mdev)) - pg_align = PFN_UP(mdev->mc.vram_size); - - return drm_gem_vram_fill_create_dumb(file, dev, pg_align, 0, args); -} - static struct drm_driver driver = { .driver_features = DRIVER_ATOMIC | DRIVER_GEM | DRIVER_MODESET, .fops = _driver_fops, @@ -148,10 +106,7 @@ static struct drm_driver driver = { .major = DRIVER_MAJOR, .minor = DRIVER_MINOR, .patchlevel = DRIVER_PATCHLEVEL, - .debugfs_init = drm_vram_mm_debugfs_init, - .dumb_create = mgag200_driver_dumb_create, - .dumb_map_offset = drm_gem_vram_driver_dumb_mmap_offset, - .gem_prime_mmap = drm_gem_prime_mmap, + DRM_GEM_SHMEM_DRIVER_OPS, }; static struct pci_driver mgag200_pci_driver = { diff --git a/drivers/gpu/drm/mgag200/mgag200_drv.h b/drivers/gpu/drm/mgag200/mgag200_drv.h index 2e407508714c8..8c37177b8fa0c 100644 --- a/drivers/gpu/drm/mgag200/mgag200_drv.h +++ b/drivers/gpu/drm/mgag200/mgag200_drv.h @@ -18,7 +18,7 @@ #include #include #include -#include +#include #include #include "mgag200_reg.h" @@ -164,7 +164,8 @@ struct mga_device { struct mga_mc mc; - size_t
[PATCH 01/17] drm/mgag200: Remove HW cursor
The HW cursor of Matrox G200 cards only supports a 16-color palette format. Univeral planes require at least ARGB or a similar component- based format. Converting a cursor image from ARGB to 16 colors does not produce pleasent-looking results in general, so remove the HW cursor. Signed-off-by: Thomas Zimmermann --- drivers/gpu/drm/mgag200/Makefile | 2 +- drivers/gpu/drm/mgag200/mgag200_cursor.c | 319 --- drivers/gpu/drm/mgag200/mgag200_drv.h| 13 - drivers/gpu/drm/mgag200/mgag200_main.c | 7 - drivers/gpu/drm/mgag200/mgag200_mode.c | 2 - 5 files changed, 1 insertion(+), 342 deletions(-) delete mode 100644 drivers/gpu/drm/mgag200/mgag200_cursor.c diff --git a/drivers/gpu/drm/mgag200/Makefile b/drivers/gpu/drm/mgag200/Makefile index 04b281bcf6558..63403133638a3 100644 --- a/drivers/gpu/drm/mgag200/Makefile +++ b/drivers/gpu/drm/mgag200/Makefile @@ -1,5 +1,5 @@ # SPDX-License-Identifier: GPL-2.0-only -mgag200-y := mgag200_main.o mgag200_mode.o mgag200_cursor.o \ +mgag200-y := mgag200_main.o mgag200_mode.o \ mgag200_drv.o mgag200_i2c.o mgag200_ttm.o obj-$(CONFIG_DRM_MGAG200) += mgag200.o diff --git a/drivers/gpu/drm/mgag200/mgag200_cursor.c b/drivers/gpu/drm/mgag200/mgag200_cursor.c deleted file mode 100644 index d491edd317ff3..0 --- a/drivers/gpu/drm/mgag200/mgag200_cursor.c +++ /dev/null @@ -1,319 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * Copyright 2013 Matrox Graphics - * - * Author: Christopher Harvey - */ - -#include - -#include "mgag200_drv.h" - -static bool warn_transparent = true; -static bool warn_palette = true; - -static int mgag200_cursor_update(struct mga_device *mdev, void *dst, void *src, -unsigned int width, unsigned int height) -{ - struct drm_device *dev = mdev->dev; - unsigned int i, row, col; - uint32_t colour_set[16]; - uint32_t *next_space = _set[0]; - uint32_t *palette_iter; - uint32_t this_colour; - bool found = false; - int colour_count = 0; - u8 reg_index; - u8 this_row[48]; - - memset(_set[0], 0, sizeof(uint32_t)*16); - /* width*height*4 = 16384 */ - for (i = 0; i < 16384; i += 4) { - this_colour = ioread32(src + i); - /* No transparency */ - if (this_colour>>24 != 0xff && - this_colour>>24 != 0x0) { - if (warn_transparent) { - dev_info(>pdev->dev, "Video card doesn't support cursors with partial transparency.\n"); - dev_info(>pdev->dev, "Not enabling hardware cursor.\n"); - warn_transparent = false; /* Only tell the user once. */ - } - return -EINVAL; - } - /* Don't need to store transparent pixels as colours */ - if (this_colour>>24 == 0x0) - continue; - found = false; - for (palette_iter = _set[0]; palette_iter != next_space; palette_iter++) { - if (*palette_iter == this_colour) { - found = true; - break; - } - } - if (found) - continue; - /* We only support 4bit paletted cursors */ - if (colour_count >= 16) { - if (warn_palette) { - dev_info(>pdev->dev, "Video card only supports cursors with up to 16 colours.\n"); - dev_info(>pdev->dev, "Not enabling hardware cursor.\n"); - warn_palette = false; /* Only tell the user once. */ - } - return -EINVAL; - } - *next_space = this_colour; - next_space++; - colour_count++; - } - - /* Program colours from cursor icon into palette */ - for (i = 0; i < colour_count; i++) { - if (i <= 2) - reg_index = 0x8 + i*0x4; - else - reg_index = 0x60 + i*0x3; - WREG_DAC(reg_index, colour_set[i] & 0xff); - WREG_DAC(reg_index+1, colour_set[i]>>8 & 0xff); - WREG_DAC(reg_index+2, colour_set[i]>>16 & 0xff); - BUG_ON((colour_set[i]>>24 & 0xff) != 0xff); - } - - /* now write colour indices into hardware cursor buffer */ - for (row = 0; row < 64; row++) { - memset(_row[0], 0, 48); - for (col = 0; col < 64; col++) { - this_colour = ioread32(src + 4*(col + 64*row)); - /* write transparent pixels */ - if (this_colour>>24 == 0x0) { - this_row[47 - col/8] |= 0x80>>(col%8); -
[PATCH 02/17] drm/mgag200: Remove unused fields from struct mga_device
The fields mode_info, num_crtcs and mode in struct mga_device serve no purpose. Remove them. Signed-off-by: Thomas Zimmermann --- drivers/gpu/drm/mgag200/mgag200_drv.h | 8 drivers/gpu/drm/mgag200/mgag200_main.c | 3 --- drivers/gpu/drm/mgag200/mgag200_mode.c | 6 -- 3 files changed, 17 deletions(-) diff --git a/drivers/gpu/drm/mgag200/mgag200_drv.h b/drivers/gpu/drm/mgag200/mgag200_drv.h index c7f2000d46fce..de3181bd63ca0 100644 --- a/drivers/gpu/drm/mgag200/mgag200_drv.h +++ b/drivers/gpu/drm/mgag200/mgag200_drv.h @@ -104,11 +104,6 @@ struct mga_crtc { bool enabled; }; -struct mga_mode_info { - bool mode_config_initialized; - struct mga_crtc *crtc; -}; - struct mga_i2c_chan { struct i2c_adapter adapter; struct drm_device *dev; @@ -155,15 +150,12 @@ struct mga_device { void __iomem*rmmio; struct mga_mc mc; - struct mga_mode_infomode_info; size_t vram_fb_available; boolsuspended; - int num_crtc; enum mga_type type; int has_sdram; - struct drm_display_mode mode; int bpp_shifts[4]; diff --git a/drivers/gpu/drm/mgag200/mgag200_main.c b/drivers/gpu/drm/mgag200/mgag200_main.c index 46cc32816f1e1..698fbf31337d4 100644 --- a/drivers/gpu/drm/mgag200/mgag200_main.c +++ b/drivers/gpu/drm/mgag200/mgag200_main.c @@ -98,9 +98,6 @@ static int mgag200_device_init(struct drm_device *dev, mdev->flags = mgag200_flags_from_driver_data(flags); mdev->type = mgag200_type_from_driver_data(flags); - /* Hardcode the number of CRTCs to 1 */ - mdev->num_crtc = 1; - pci_read_config_dword(dev->pdev, PCI_MGA_OPTION, ); mdev->has_sdram = !(option & (1 << 14)); diff --git a/drivers/gpu/drm/mgag200/mgag200_mode.c b/drivers/gpu/drm/mgag200/mgag200_mode.c index c9d120b019649..ce41bebfdd1a2 100644 --- a/drivers/gpu/drm/mgag200/mgag200_mode.c +++ b/drivers/gpu/drm/mgag200/mgag200_mode.c @@ -1135,9 +1135,6 @@ static int mga_crtc_mode_set(struct drm_crtc *crtc, WREG8(MGA_MISC_OUT, misc); - if (adjusted_mode) - memcpy(>mode, mode, sizeof(struct drm_display_mode)); - mga_crtc_do_set_base(crtc, old_fb, x, y, 0); /* reset tagfifo */ @@ -1443,7 +1440,6 @@ static void mga_crtc_init(struct mga_device *mdev) drm_crtc_init(mdev->dev, _crtc->base, _crtc_funcs); drm_mode_crtc_set_gamma_size(_crtc->base, MGAG200_LUT_SIZE); - mdev->mode_info.crtc = mga_crtc; drm_crtc_helper_add(_crtc->base, _helper_funcs); } @@ -1619,8 +1615,6 @@ int mgag200_modeset_init(struct mga_device *mdev) struct drm_connector *connector; int ret; - mdev->mode_info.mode_config_initialized = true; - mdev->dev->mode_config.max_width = MGAG200_MAX_FB_WIDTH; mdev->dev->mode_config.max_height = MGAG200_MAX_FB_HEIGHT; -- 2.26.0 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH 12/17] drm/mgag200: Move TAGFIFO reset into separate function
The TAGFIFO state is now reset in mgag200_g200er_reset_tagfifo(). Signed-off-by: Thomas Zimmermann --- drivers/gpu/drm/mgag200/mgag200_drv.h | 6 drivers/gpu/drm/mgag200/mgag200_mode.c | 45 +- 2 files changed, 35 insertions(+), 16 deletions(-) diff --git a/drivers/gpu/drm/mgag200/mgag200_drv.h b/drivers/gpu/drm/mgag200/mgag200_drv.h index 9b957d9fc7e04..b10da90e0f35a 100644 --- a/drivers/gpu/drm/mgag200/mgag200_drv.h +++ b/drivers/gpu/drm/mgag200/mgag200_drv.h @@ -49,6 +49,12 @@ WREG8(ATTR_DATA, v);\ } while (0) \ +#define RREG_SEQ(reg, v) \ + do {\ + WREG8(MGAREG_SEQ_INDEX, reg); \ + v = RREG8(MGAREG_SEQ_DATA); \ + } while (0) \ + #define WREG_SEQ(reg, v) \ do {\ WREG8(MGAREG_SEQ_INDEX, reg); \ diff --git a/drivers/gpu/drm/mgag200/mgag200_mode.c b/drivers/gpu/drm/mgag200/mgag200_mode.c index 73f7135cbb3d8..6b88c306ff4d7 100644 --- a/drivers/gpu/drm/mgag200/mgag200_mode.c +++ b/drivers/gpu/drm/mgag200/mgag200_mode.c @@ -1091,6 +1091,33 @@ static void mgag200_set_format_regs(struct mga_device *mdev, WREG_ECRT(3, crtcext3); } +static void mgag200_g200er_reset_tagfifo(struct mga_device *mdev) +{ + static uint32_t RESET_FLAG = 0x0020; /* undocumented magic value */ + u8 seq1; + u32 memctl; + + /* screen off */ + RREG_SEQ(0x01, seq1); + seq1 |= 0x20; + WREG_SEQ(0x01, seq1); + + memctl = RREG32(MGAREG_MEMCTL); + + memctl |= RESET_FLAG; + WREG32(MGAREG_MEMCTL, memctl); + + udelay(1000); + + memctl &= ~RESET_FLAG; + WREG32(MGAREG_MEMCTL, memctl); + + /* screen on */ + RREG_SEQ(0x01, seq1); + seq1 &= ~0x20; + WREG_SEQ(0x01, seq1); +} + static int mga_crtc_mode_set(struct drm_crtc *crtc, struct drm_display_mode *mode, struct drm_display_mode *adjusted_mode, @@ -1225,22 +1252,8 @@ static int mga_crtc_mode_set(struct drm_crtc *crtc, mgag200_set_mode_regs(mdev, mode); - /* reset tagfifo */ - if (mdev->type == G200_ER) { - u32 mem_ctl = RREG32(MGAREG_MEMCTL); - u8 seq1; - - /* screen off */ - WREG8(MGAREG_SEQ_INDEX, 0x01); - seq1 = RREG8(MGAREG_SEQ_DATA) | 0x20; - WREG8(MGAREG_SEQ_DATA, seq1); - - WREG32(MGAREG_MEMCTL, mem_ctl | 0x0020); - udelay(1000); - WREG32(MGAREG_MEMCTL, mem_ctl & ~0x0020); - - WREG8(MGAREG_SEQ_DATA, seq1 & ~0x20); - } + if (mdev->type == G200_ER) + mgag200_g200er_reset_tagfifo(mdev); if (IS_G200_SE(mdev)) { -- 2.26.0 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH 07/17] drm/mgag200: Move mode-setting code into separate helper function
The mode-setting code is now located in mgag200_set_mode_regs(), sans a few flags that will be moved in a later patch for clarity. Signed-off-by: Thomas Zimmermann --- drivers/gpu/drm/mgag200/mgag200_mode.c | 140 ++--- 1 file changed, 78 insertions(+), 62 deletions(-) diff --git a/drivers/gpu/drm/mgag200/mgag200_mode.c b/drivers/gpu/drm/mgag200/mgag200_mode.c index 12df809d64f7c..749ba6e420ac7 100644 --- a/drivers/gpu/drm/mgag200/mgag200_mode.c +++ b/drivers/gpu/drm/mgag200/mgag200_mode.c @@ -911,6 +911,79 @@ static int mga_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y, return mga_crtc_do_set_base(mdev, fb, old_fb); } +static void mgag200_set_mode_regs(struct mga_device *mdev, + const struct drm_display_mode *mode) +{ + unsigned int hdisplay, hsyncstart, hsyncend, htotal; + unsigned int vdisplay, vsyncstart, vsyncend, vtotal; + uint8_t misc = 0; + uint8_t crtcext1, crtcext2, crtcext5; + + hdisplay = mode->hdisplay / 8 - 1; + hsyncstart = mode->hsync_start / 8 - 1; + hsyncend = mode->hsync_end / 8 - 1; + htotal = mode->htotal / 8 - 1; + + /* Work around hardware quirk */ + if ((htotal & 0x07) == 0x06 || (htotal & 0x07) == 0x04) + htotal++; + + vdisplay = mode->vdisplay - 1; + vsyncstart = mode->vsync_start - 1; + vsyncend = mode->vsync_end - 1; + vtotal = mode->vtotal - 2; + + if (mode->flags & DRM_MODE_FLAG_NHSYNC) + misc |= 0x40; + if (mode->flags & DRM_MODE_FLAG_NVSYNC) + misc |= 0x80; + + crtcext1 = (((htotal - 4) & 0x100) >> 8) | + ((hdisplay & 0x100) >> 7) | + ((hsyncstart & 0x100) >> 6) | + (htotal & 0x40); + if (mdev->type == G200_WB || mdev->type == G200_EW3) + crtcext1 |= BIT(7) | /* vrsten */ + BIT(3); /* hrsten */ + + crtcext2 = ((vtotal & 0xc00) >> 10) | + ((vdisplay & 0x400) >> 8) | + ((vdisplay & 0xc00) >> 7) | + ((vsyncstart & 0xc00) >> 5) | + ((vdisplay & 0x400) >> 3); + crtcext5 = 0x00; + + WREG_CRT(0, htotal - 4); + WREG_CRT(1, hdisplay); + WREG_CRT(2, hdisplay); + WREG_CRT(3, (htotal & 0x1F) | 0x80); + WREG_CRT(4, hsyncstart); + WREG_CRT(5, ((htotal & 0x20) << 2) | (hsyncend & 0x1F)); + WREG_CRT(6, vtotal & 0xFF); + WREG_CRT(7, ((vtotal & 0x100) >> 8) | +((vdisplay & 0x100) >> 7) | +((vsyncstart & 0x100) >> 6) | +((vdisplay & 0x100) >> 5) | +((vdisplay & 0x100) >> 4) | /* linecomp */ +((vtotal & 0x200) >> 4) | +((vdisplay & 0x200) >> 3) | +((vsyncstart & 0x200) >> 2)); + WREG_CRT(9, ((vdisplay & 0x200) >> 4) | +((vdisplay & 0x200) >> 3)); + WREG_CRT(16, vsyncstart & 0xFF); + WREG_CRT(17, (vsyncend & 0x0F) | 0x20); + WREG_CRT(18, vdisplay & 0xFF); + WREG_CRT(20, 0); + WREG_CRT(21, vdisplay & 0xFF); + WREG_CRT(22, (vtotal + 1) & 0xFF); + WREG_CRT(23, 0xc3); + WREG_CRT(24, vdisplay & 0xFF); + + WREG_ECRT(0x01, crtcext1); + WREG_ECRT(0x02, crtcext2); + WREG_ECRT(0x05, crtcext5); +} + static int mga_crtc_mode_set(struct drm_crtc *crtc, struct drm_display_mode *mode, struct drm_display_mode *adjusted_mode, @@ -919,8 +992,6 @@ static int mga_crtc_mode_set(struct drm_crtc *crtc, struct drm_device *dev = crtc->dev; struct mga_device *mdev = dev->dev_private; const struct drm_framebuffer *fb = crtc->primary->fb; - int hdisplay, hsyncstart, hsyncend, htotal; - int vdisplay, vsyncstart, vsyncend, vtotal; int pitch; int option = 0, option2 = 0; int i; @@ -999,12 +1070,6 @@ static int mga_crtc_mode_set(struct drm_crtc *crtc, break; } - if (mode->flags & DRM_MODE_FLAG_NHSYNC) - misc |= 0x40; - if (mode->flags & DRM_MODE_FLAG_NVSYNC) - misc |= 0x80; - - for (i = 0; i < sizeof(dacvalue); i++) { if ((i <= 0x17) || (i == 0x1b) || @@ -1044,20 +1109,6 @@ static int mga_crtc_mode_set(struct drm_crtc *crtc, else pitch = pitch >> (4 - bppshift); - hdisplay = mode->hdisplay / 8 - 1; - hsyncstart = mode->hsync_start / 8 - 1; - hsyncend = mode->hsync_end / 8 - 1; - htotal = mode->htotal / 8 - 1; - - /* Work around hardware quirk */ - if ((htotal & 0x07) == 0x06 || (htotal & 0x07) == 0x04) - htotal++; - - vdisplay = mode->vdisplay - 1; - vsyncstart = mode->vsync_start - 1; - vsyncend = mode->vsync_end - 1; - vtotal = mode->vtotal - 2; -
[PATCH 11/17] drm/mgag200: Set primary plane's format in separate helper function
The primary plane's format registers are now updated in a mgag200_set_format_regs(). Signed-off-by: Thomas Zimmermann --- drivers/gpu/drm/mgag200/mgag200_mode.c | 109 - 1 file changed, 69 insertions(+), 40 deletions(-) diff --git a/drivers/gpu/drm/mgag200/mgag200_mode.c b/drivers/gpu/drm/mgag200/mgag200_mode.c index eb83e471d72fc..73f7135cbb3d8 100644 --- a/drivers/gpu/drm/mgag200/mgag200_mode.c +++ b/drivers/gpu/drm/mgag200/mgag200_mode.c @@ -1029,6 +1029,68 @@ static void mgag200_set_offset(struct mga_device *mdev, WREG_ECRT(0x00, crtcext0); } +static void mgag200_set_format_regs(struct mga_device *mdev, + const struct drm_framebuffer *fb) +{ + struct drm_device *dev = mdev->dev; + const struct drm_format_info *format = fb->format; + unsigned int bpp, bppshift, scale; + uint8_t crtcext3, xmulctrl; + + bpp = format->cpp[0] * 8; + + bppshift = mdev->bpp_shifts[format->cpp[0] - 1]; + switch (bpp) { + case 24: + scale = ((1 << bppshift) * 3) - 1; + break; + default: + scale = (1 << bppshift) - 1; + break; + } + + RREG_ECRT(3, crtcext3); + + switch (bpp) { + case 8: + xmulctrl = MGA1064_MUL_CTL_8bits; + break; + case 16: + if (format->depth == 15) + xmulctrl = MGA1064_MUL_CTL_15bits; + else + xmulctrl = MGA1064_MUL_CTL_16bits; + break; + case 24: + xmulctrl = MGA1064_MUL_CTL_24bits; + break; + case 32: + xmulctrl = MGA1064_MUL_CTL_32_24bits; + break; + default: + /* BUG: We should have caught this problem already. */ + drm_WARN_ON(dev, "invalid format depth\n"); + return; + } + + crtcext3 &= ~GENMASK(2, 0); + crtcext3 |= scale; + + WREG_DAC(MGA1064_MUL_CTL, xmulctrl); + + WREG_GFX(0, 0x00); + WREG_GFX(1, 0x00); + WREG_GFX(2, 0x00); + WREG_GFX(3, 0x00); + WREG_GFX(4, 0x00); + WREG_GFX(5, 0x40); + WREG_GFX(6, 0x05); + WREG_GFX(7, 0x0f); + WREG_GFX(8, 0x0f); + + WREG_ECRT(3, crtcext3); +} + static int mga_crtc_mode_set(struct drm_crtc *crtc, struct drm_display_mode *mode, struct drm_display_mode *adjusted_mode, @@ -1040,8 +1102,7 @@ static int mga_crtc_mode_set(struct drm_crtc *crtc, int option = 0, option2 = 0; int i; unsigned char misc = 0; - unsigned char ext_vga[6]; - u8 bppshift; + uint8_t crtcext3, crtcext4; static unsigned char dacvalue[] = { /* 0x00: */0,0,0,0,0,0, 0x00,0, @@ -1056,8 +1117,6 @@ static int mga_crtc_mode_set(struct drm_crtc *crtc, /* 0x48: */0,0,0,0,0,0,0,0 }; - bppshift = mdev->bpp_shifts[fb->format->cpp[0] - 1]; - switch (mdev->type) { case G200_SE_A: case G200_SE_B: @@ -1096,24 +1155,6 @@ static int mga_crtc_mode_set(struct drm_crtc *crtc, break; } - switch (fb->format->cpp[0] * 8) { - case 8: - dacvalue[MGA1064_MUL_CTL] = MGA1064_MUL_CTL_8bits; - break; - case 16: - if (fb->format->depth == 15) - dacvalue[MGA1064_MUL_CTL] = MGA1064_MUL_CTL_15bits; - else - dacvalue[MGA1064_MUL_CTL] = MGA1064_MUL_CTL_16bits; - break; - case 24: - dacvalue[MGA1064_MUL_CTL] = MGA1064_MUL_CTL_24bits; - break; - case 32: - dacvalue[MGA1064_MUL_CTL] = MGA1064_MUL_CTL_32_24bits; - break; - } - for (i = 0; i < sizeof(dacvalue); i++) { if ((i <= 0x17) || (i == 0x1b) || @@ -1147,16 +1188,6 @@ static int mga_crtc_mode_set(struct drm_crtc *crtc, WREG_SEQ(3, 0); WREG_SEQ(4, 0xe); - WREG_GFX(0, 0); - WREG_GFX(1, 0); - WREG_GFX(2, 0); - WREG_GFX(3, 0); - WREG_GFX(4, 0); - WREG_GFX(5, 0x40); - WREG_GFX(6, 0x5); - WREG_GFX(7, 0xf); - WREG_GFX(8, 0xf); - WREG_CRT(10, 0); WREG_CRT(11, 0); WREG_CRT(12, 0); @@ -1164,16 +1195,13 @@ static int mga_crtc_mode_set(struct drm_crtc *crtc, WREG_CRT(14, 0); WREG_CRT(15, 0); - /* TODO interlace */ + RREG_ECRT(0x03, crtcext3); - if (fb->format->cpp[0] * 8 == 24) - ext_vga[3] = (((1 << bppshift) * 3) - 1) | 0x80; - else - ext_vga[3] = ((1 << bppshift) - 1) | 0x80; - ext_vga[4] = 0; + crtcext3 |= BIT(7); /* enable MGA mode */ + crtcext4 = 0x00; -
[PATCH 08/17] drm/mgag200: Split MISC register update into PLL selection, SYNC and I/O
Set different fields in MISC in their rsp location in the code. This patch also fixes a bug in the original code where the mode's SYNC flags were never written into the MISC register. Signed-off-by: Thomas Zimmermann --- drivers/gpu/drm/mgag200/mgag200_mode.c | 37 ++ drivers/gpu/drm/mgag200/mgag200_reg.h | 5 +++- 2 files changed, 30 insertions(+), 12 deletions(-) diff --git a/drivers/gpu/drm/mgag200/mgag200_mode.c b/drivers/gpu/drm/mgag200/mgag200_mode.c index 749ba6e420ac7..b5bb02e9f05d6 100644 --- a/drivers/gpu/drm/mgag200/mgag200_mode.c +++ b/drivers/gpu/drm/mgag200/mgag200_mode.c @@ -704,6 +704,8 @@ static int mga_g200er_set_plls(struct mga_device *mdev, long clock) static int mga_crtc_set_plls(struct mga_device *mdev, long clock) { + uint8_t misc; + switch(mdev->type) { case G200_SE_A: case G200_SE_B: @@ -724,6 +726,12 @@ static int mga_crtc_set_plls(struct mga_device *mdev, long clock) return mga_g200er_set_plls(mdev, clock); break; } + + misc = RREG8(MGA_MISC_IN); + misc &= ~GENMASK(3, 2); + misc |= MGAREG_MISC_CLK_SEL_MGA_MSK; + WREG8(MGA_MISC_OUT, misc); + return 0; } @@ -916,7 +924,7 @@ static void mgag200_set_mode_regs(struct mga_device *mdev, { unsigned int hdisplay, hsyncstart, hsyncend, htotal; unsigned int vdisplay, vsyncstart, vsyncend, vtotal; - uint8_t misc = 0; + uint8_t misc; uint8_t crtcext1, crtcext2, crtcext5; hdisplay = mode->hdisplay / 8 - 1; @@ -933,10 +941,17 @@ static void mgag200_set_mode_regs(struct mga_device *mdev, vsyncend = mode->vsync_end - 1; vtotal = mode->vtotal - 2; + misc = RREG8(MGA_MISC_IN); + if (mode->flags & DRM_MODE_FLAG_NHSYNC) - misc |= 0x40; + misc |= MGAREG_MISC_HSYNCPOL; + else + misc &= ~MGAREG_MISC_HSYNCPOL; + if (mode->flags & DRM_MODE_FLAG_NVSYNC) - misc |= 0x80; + misc |= MGAREG_MISC_VSYNCPOL; + else + misc &= ~MGAREG_MISC_VSYNCPOL; crtcext1 = (((htotal - 4) & 0x100) >> 8) | ((hdisplay & 0x100) >> 7) | @@ -982,6 +997,10 @@ static void mgag200_set_mode_regs(struct mga_device *mdev, WREG_ECRT(0x01, crtcext1); WREG_ECRT(0x02, crtcext2); WREG_ECRT(0x05, crtcext5); + + WREG8(MGA_MISC_OUT, misc); + + mga_crtc_set_plls(mdev, mode->clock); } static int mga_crtc_mode_set(struct drm_crtc *crtc, @@ -1140,12 +1159,6 @@ static int mga_crtc_mode_set(struct drm_crtc *crtc, ext_vga[3] = ((1 << bppshift) - 1) | 0x80; ext_vga[4] = 0; - /* Set pixel clocks */ - misc = 0x2d; - WREG8(MGA_MISC_OUT, misc); - - mga_crtc_set_plls(mdev, mode->clock); - WREG_ECRT(0, ext_vga[0]); WREG_ECRT(3, ext_vga[3]); WREG_ECRT(4, ext_vga[4]); @@ -1161,9 +1174,11 @@ static int mga_crtc_mode_set(struct drm_crtc *crtc, } WREG_ECRT(0, ext_vga[0]); - /* Enable mga pixel clock */ - misc = 0x2d; + misc = RREG8(MGA_MISC_IN); + misc |= MGAREG_MISC_IOADSEL | + MGAREG_MISC_RAMMAPEN | + MGAREG_MISC_HIGH_PG_SEL; WREG8(MGA_MISC_OUT, misc); mga_crtc_do_set_base(mdev, fb, old_fb); diff --git a/drivers/gpu/drm/mgag200/mgag200_reg.h b/drivers/gpu/drm/mgag200/mgag200_reg.h index c096a9d6bcbc1..89e12c55153cf 100644 --- a/drivers/gpu/drm/mgag200/mgag200_reg.h +++ b/drivers/gpu/drm/mgag200/mgag200_reg.h @@ -16,10 +16,11 @@ * MGA1064SG Mystique register file */ - #ifndef _MGA_REG_H_ #define _MGA_REG_H_ +#include + #defineMGAREG_DWGCTL 0x1c00 #defineMGAREG_MACCESS 0x1c04 /* the following is a mystique only register */ @@ -227,6 +228,8 @@ #define MGAREG_MISC_CLK_SEL_MGA_MSK(0x3 << 2) #define MGAREG_MISC_VIDEO_DIS (0x1 << 4) #define MGAREG_MISC_HIGH_PG_SEL(0x1 << 5) +#define MGAREG_MISC_HSYNCPOL BIT(6) +#define MGAREG_MISC_VSYNCPOL BIT(7) /* MMIO VGA registers */ #define MGAREG_SEQ_INDEX 0x1fc4 -- 2.26.0 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH 06/17] drm/mgag200: Clean up mga_crtc_do_set_base()
The function now only takes the device structure, and the old and new framebuffers. Signed-off-by: Thomas Zimmermann --- drivers/gpu/drm/mgag200/mgag200_mode.c | 18 +- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/mgag200/mgag200_mode.c b/drivers/gpu/drm/mgag200/mgag200_mode.c index b16a73c8617d6..12df809d64f7c 100644 --- a/drivers/gpu/drm/mgag200/mgag200_mode.c +++ b/drivers/gpu/drm/mgag200/mgag200_mode.c @@ -861,21 +861,20 @@ static void mgag200_set_startadd(struct mga_device *mdev, WREG_ECRT(0x00, crtcext0); } -static int mga_crtc_do_set_base(struct drm_crtc *crtc, - struct drm_framebuffer *fb, - int x, int y, int atomic) +static int mga_crtc_do_set_base(struct mga_device *mdev, + const struct drm_framebuffer *fb, + const struct drm_framebuffer *old_fb) { - struct mga_device *mdev = crtc->dev->dev_private; struct drm_gem_vram_object *gbo; int ret; s64 gpu_addr; - if (!atomic && fb) { - gbo = drm_gem_vram_of_gem(fb->obj[0]); + if (old_fb) { + gbo = drm_gem_vram_of_gem(old_fb->obj[0]); drm_gem_vram_unpin(gbo); } - gbo = drm_gem_vram_of_gem(crtc->primary->fb->obj[0]); + gbo = drm_gem_vram_of_gem(fb->obj[0]); ret = drm_gem_vram_pin(gbo, DRM_GEM_VRAM_PL_FLAG_VRAM); if (ret) @@ -900,6 +899,7 @@ static int mga_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y, { struct drm_device *dev = crtc->dev; struct mga_device *mdev = dev->dev_private; + struct drm_framebuffer *fb = crtc->primary->fb; unsigned int count; while (RREG8(0x1fda) & 0x08) { } @@ -908,7 +908,7 @@ static int mga_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y, count = RREG8(MGAREG_VCOUNT) + 2; while (RREG8(MGAREG_VCOUNT) < count) { } - return mga_crtc_do_set_base(crtc, old_fb, x, y, 0); + return mga_crtc_do_set_base(mdev, fb, old_fb); } static int mga_crtc_mode_set(struct drm_crtc *crtc, @@ -1150,7 +1150,7 @@ static int mga_crtc_mode_set(struct drm_crtc *crtc, WREG8(MGA_MISC_OUT, misc); - mga_crtc_do_set_base(crtc, old_fb, x, y, 0); + mga_crtc_do_set_base(mdev, fb, old_fb); /* reset tagfifo */ if (mdev->type == G200_ER) { -- 2.26.0 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH 05/17] drm/mgag200: Clean up mga_set_start_address()
All register names and fields are now named according to the MGA programming manuals. The function doesn't need the CRTC, so callers pass in the device structure directly. The logging now uses device-specific macros. Signed-off-by: Thomas Zimmermann --- drivers/gpu/drm/mgag200/mgag200_drv.h | 5 ++ drivers/gpu/drm/mgag200/mgag200_mode.c | 82 +++--- 2 files changed, 53 insertions(+), 34 deletions(-) diff --git a/drivers/gpu/drm/mgag200/mgag200_drv.h b/drivers/gpu/drm/mgag200/mgag200_drv.h index 4403145e3593c..9b957d9fc7e04 100644 --- a/drivers/gpu/drm/mgag200/mgag200_drv.h +++ b/drivers/gpu/drm/mgag200/mgag200_drv.h @@ -61,6 +61,11 @@ WREG8(MGAREG_CRTC_DATA, v); \ } while (0) \ +#define RREG_ECRT(reg, v) \ + do {\ + WREG8(MGAREG_CRTCEXT_INDEX, reg); \ + v = RREG8(MGAREG_CRTCEXT_DATA); \ + } while (0) \ #define WREG_ECRT(reg, v) \ do {\ diff --git a/drivers/gpu/drm/mgag200/mgag200_mode.c b/drivers/gpu/drm/mgag200/mgag200_mode.c index 3d894b37a0812..b16a73c8617d6 100644 --- a/drivers/gpu/drm/mgag200/mgag200_mode.c +++ b/drivers/gpu/drm/mgag200/mgag200_mode.c @@ -819,49 +819,53 @@ static void mga_g200wb_commit(struct drm_crtc *crtc) } /* - This is how the framebuffer base address is stored in g200 cards: - * Assume @offset is the gpu_addr variable of the framebuffer object - * Then addr is the number of _pixels_ (not bytes) from the start of - VRAM to the first pixel we want to display. (divided by 2 for 32bit - framebuffers) - * addr is stored in the CRTCEXT0, CRTCC and CRTCD registers - addr<20> -> CRTCEXT0<6> - addr<19-16> -> CRTCEXT0<3-0> - addr<15-8> -> CRTCC<7-0> - addr<7-0> -> CRTCD<7-0> - CRTCEXT0 has to be programmed last to trigger an update and make the - new addr variable take effect. + * This is how the framebuffer base address is stored in g200 cards: + * * Assume @offset is the gpu_addr variable of the framebuffer object + * * Then addr is the number of _pixels_ (not bytes) from the start of + * VRAM to the first pixel we want to display. (divided by 2 for 32bit + * framebuffers) + * * addr is stored in the CRTCEXT0, CRTCC and CRTCD registers + * addr<20> -> CRTCEXT0<6> + * addr<19-16> -> CRTCEXT0<3-0> + * addr<15-8> -> CRTCC<7-0> + * addr<7-0> -> CRTCD<7-0> + * + * CRTCEXT0 has to be programmed last to trigger an update and make the + * new addr variable take effect. */ -static void mga_set_start_address(struct drm_crtc *crtc, unsigned offset) +static void mgag200_set_startadd(struct mga_device *mdev, +unsigned long offset) { - struct mga_device *mdev = crtc->dev->dev_private; - u32 addr; - int count; - u8 crtcext0; + struct drm_device *dev = mdev->dev; + uint32_t startadd; + uint8_t crtcc, crtcd, crtcext0; - while (RREG8(0x1fda) & 0x08); - while (!(RREG8(0x1fda) & 0x08)); + startadd = offset / 8; - count = RREG8(MGAREG_VCOUNT) + 2; - while (RREG8(MGAREG_VCOUNT) < count); - - WREG8(MGAREG_CRTCEXT_INDEX, 0); - crtcext0 = RREG8(MGAREG_CRTCEXT_DATA); - crtcext0 &= 0xB0; - addr = offset / 8; - /* Can't store addresses any higher than that... - but we also don't have more than 16MB of memory, so it should be fine. */ - WARN_ON(addr > 0x1f); - crtcext0 |= (!!(addr & (1<<20)))<<6; - WREG_CRT(0x0d, (u8)(addr & 0xff)); - WREG_CRT(0x0c, (u8)(addr >> 8) & 0xff); - WREG_ECRT(0x0, ((u8)(addr >> 16) & 0xf) | crtcext0); + /* +* Can't store addresses any higher than that, but we also +* don't have more than 16MB of memory, so it should be fine. +*/ + drm_WARN_ON(dev, startadd > 0x1f); + + RREG_ECRT(0x00, crtcext0); + + crtcc = (startadd >> 8) & 0xff; + crtcd = startadd & 0xff; + crtcext0 &= 0xb0; + crtcext0 |= ((startadd >> 14) & BIT(6)) | + ((startadd >> 16) & 0x0f); + + WREG_CRT(0x0c, crtcc); + WREG_CRT(0x0d, crtcd); + WREG_ECRT(0x00, crtcext0); } static int mga_crtc_do_set_base(struct drm_crtc *crtc, struct drm_framebuffer *fb, int x, int y, int atomic) { + struct mga_device *mdev = crtc->dev->dev_private; struct drm_gem_vram_object *gbo; int ret; s64 gpu_addr; @@ -882,7 +886,7 @@ static int mga_crtc_do_set_base(struct drm_crtc *crtc, goto err_drm_gem_vram_unpin; } - mga_set_start_address(crtc, (u32)gpu_addr); +
[PATCH 16/17] drm/mgag200: Convert to simple KMS helper
The mgag200 supports a single pipeline with only a primary plane. It can be converted to simple KMS helpers. This also adds support for atomic modesetting. Wayland compositors, which use pageflip ioctls, can now be used with mgag200. Signed-off-by: Thomas Zimmermann --- drivers/gpu/drm/mgag200/mgag200_drv.c | 2 +- drivers/gpu/drm/mgag200/mgag200_drv.h | 4 +- drivers/gpu/drm/mgag200/mgag200_mode.c | 396 +++-- 3 files changed, 171 insertions(+), 231 deletions(-) diff --git a/drivers/gpu/drm/mgag200/mgag200_drv.c b/drivers/gpu/drm/mgag200/mgag200_drv.c index 3298b7ef18b03..b1272165621ed 100644 --- a/drivers/gpu/drm/mgag200/mgag200_drv.c +++ b/drivers/gpu/drm/mgag200/mgag200_drv.c @@ -140,7 +140,7 @@ int mgag200_driver_dumb_create(struct drm_file *file, } static struct drm_driver driver = { - .driver_features = DRIVER_GEM | DRIVER_MODESET, + .driver_features = DRIVER_ATOMIC | DRIVER_GEM | DRIVER_MODESET, .fops = _driver_fops, .name = DRIVER_NAME, .desc = DRIVER_DESC, diff --git a/drivers/gpu/drm/mgag200/mgag200_drv.h b/drivers/gpu/drm/mgag200/mgag200_drv.h index b10da90e0f35a..2e407508714c8 100644 --- a/drivers/gpu/drm/mgag200/mgag200_drv.h +++ b/drivers/gpu/drm/mgag200/mgag200_drv.h @@ -19,6 +19,7 @@ #include #include #include +#include #include "mgag200_reg.h" @@ -107,6 +108,7 @@ #define to_mga_crtc(x) container_of(x, struct mga_crtc, base) #define to_mga_connector(x) container_of(x, struct mga_connector, base) +#define to_mga_device(x) (dev->dev_private) struct mga_crtc { struct drm_crtc base; @@ -176,7 +178,7 @@ struct mga_device { u32 unique_rev_id; struct mga_connector connector; - struct drm_encoder encoder; + struct drm_simple_display_pipe display_pipe; }; static inline enum mga_type diff --git a/drivers/gpu/drm/mgag200/mgag200_mode.c b/drivers/gpu/drm/mgag200/mgag200_mode.c index 884fc668a6dae..d9b4055e38982 100644 --- a/drivers/gpu/drm/mgag200/mgag200_mode.c +++ b/drivers/gpu/drm/mgag200/mgag200_mode.c @@ -11,10 +11,13 @@ #include #include +#include +#include #include #include #include #include +#include #include #include @@ -30,13 +33,18 @@ static void mga_crtc_load_lut(struct drm_crtc *crtc) { struct drm_device *dev = crtc->dev; struct mga_device *mdev = dev->dev_private; - struct drm_framebuffer *fb = crtc->primary->fb; + struct drm_framebuffer *fb; u16 *r_ptr, *g_ptr, *b_ptr; int i; if (!crtc->enabled) return; + if (!mdev->display_pipe.plane.state) + return; + + fb = mdev->display_pipe.plane.state->fb; + r_ptr = crtc->gamma_store; g_ptr = r_ptr + crtc->gamma_size; b_ptr = g_ptr + crtc->gamma_size; @@ -845,56 +853,6 @@ static void mgag200_set_startadd(struct mga_device *mdev, WREG_ECRT(0x00, crtcext0); } -static int mga_crtc_do_set_base(struct mga_device *mdev, - const struct drm_framebuffer *fb, - const struct drm_framebuffer *old_fb) -{ - struct drm_gem_vram_object *gbo; - int ret; - s64 gpu_addr; - - if (old_fb) { - gbo = drm_gem_vram_of_gem(old_fb->obj[0]); - drm_gem_vram_unpin(gbo); - } - - gbo = drm_gem_vram_of_gem(fb->obj[0]); - - ret = drm_gem_vram_pin(gbo, DRM_GEM_VRAM_PL_FLAG_VRAM); - if (ret) - return ret; - gpu_addr = drm_gem_vram_offset(gbo); - if (gpu_addr < 0) { - ret = (int)gpu_addr; - goto err_drm_gem_vram_unpin; - } - - mgag200_set_startadd(mdev, (unsigned long)gpu_addr); - - return 0; - -err_drm_gem_vram_unpin: - drm_gem_vram_unpin(gbo); - return ret; -} - -static int mga_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y, - struct drm_framebuffer *old_fb) -{ - struct drm_device *dev = crtc->dev; - struct mga_device *mdev = dev->dev_private; - struct drm_framebuffer *fb = crtc->primary->fb; - unsigned int count; - - while (RREG8(0x1fda) & 0x08) { } - while (!(RREG8(0x1fda) & 0x08)) { } - - count = RREG8(MGAREG_VCOUNT) + 2; - while (RREG8(MGAREG_VCOUNT) < count) { } - - return mga_crtc_do_set_base(mdev, fb, old_fb); -} - static void mgag200_set_pci_regs(struct mga_device *mdev) { uint32_t option = 0, option2 = 0; @@ -1291,93 +1249,6 @@ static void mgag200_g200ev_set_hiprilvl(struct mga_device *mdev) WREG_ECRT(0x06, 0x00); } -static int mga_crtc_mode_set(struct drm_crtc *crtc, - struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode, - int x, int y, struct drm_framebuffer *old_fb) -{ - struct drm_device *dev = crtc->dev; - struct mga_device *mdev =
[PATCH 03/17] drm/mgag200: Embed connector instance in struct mga_device
Storing the connector instance in struct mga_device avoids some dynamic memory allocation. Done im preparation of converting mgag200 to simple-KMS helpers. Signed-off-by: Thomas Zimmermann --- drivers/gpu/drm/mgag200/mgag200_drv.h | 1 + drivers/gpu/drm/mgag200/mgag200_mode.c | 54 ++ 2 files changed, 31 insertions(+), 24 deletions(-) diff --git a/drivers/gpu/drm/mgag200/mgag200_drv.h b/drivers/gpu/drm/mgag200/mgag200_drv.h index de3181bd63ca0..09b43a0ff6bbf 100644 --- a/drivers/gpu/drm/mgag200/mgag200_drv.h +++ b/drivers/gpu/drm/mgag200/mgag200_drv.h @@ -164,6 +164,7 @@ struct mga_device { /* SE model number stored in reg 0x1e24 */ u32 unique_rev_id; + struct mga_connector connector; struct drm_encoder encoder; }; diff --git a/drivers/gpu/drm/mgag200/mgag200_mode.c b/drivers/gpu/drm/mgag200/mgag200_mode.c index ce41bebfdd1a2..eaa3fca7216ac 100644 --- a/drivers/gpu/drm/mgag200/mgag200_mode.c +++ b/drivers/gpu/drm/mgag200/mgag200_mode.c @@ -1444,6 +1444,10 @@ static void mga_crtc_init(struct mga_device *mdev) drm_crtc_helper_add(_crtc->base, _helper_funcs); } +/* + * Connector + */ + static int mga_vga_get_modes(struct drm_connector *connector) { struct mga_connector *mga_connector = to_mga_connector(connector); @@ -1568,7 +1572,6 @@ static void mga_connector_destroy(struct drm_connector *connector) struct mga_connector *mga_connector = to_mga_connector(connector); mgag200_i2c_destroy(mga_connector->i2c); drm_connector_cleanup(connector); - kfree(connector); } static const struct drm_connector_helper_funcs mga_vga_connector_helper_funcs = { @@ -1582,37 +1585,39 @@ static const struct drm_connector_funcs mga_vga_connector_funcs = { .destroy = mga_connector_destroy, }; -static struct drm_connector *mga_vga_init(struct drm_device *dev) +static int mgag200_vga_connector_init(struct mga_device *mdev) { - struct drm_connector *connector; - struct mga_connector *mga_connector; - - mga_connector = kzalloc(sizeof(struct mga_connector), GFP_KERNEL); - if (!mga_connector) - return NULL; - - connector = _connector->base; - mga_connector->i2c = mgag200_i2c_create(dev); - if (!mga_connector->i2c) - DRM_ERROR("failed to add ddc bus\n"); + struct drm_device *dev = mdev->dev; + struct mga_connector *mconnector = >connector; + struct drm_connector *connector = >base; + struct mga_i2c_chan *i2c; + int ret; - drm_connector_init_with_ddc(dev, connector, - _vga_connector_funcs, - DRM_MODE_CONNECTOR_VGA, - _connector->i2c->adapter); + i2c = mgag200_i2c_create(dev); + if (!i2c) + drm_warn(dev, "failed to add DDC bus\n"); + ret = drm_connector_init_with_ddc(dev, connector, + _vga_connector_funcs, + DRM_MODE_CONNECTOR_VGA, + >adapter); + if (ret) + goto err_mgag200_i2c_destroy; drm_connector_helper_add(connector, _vga_connector_helper_funcs); - drm_connector_register(connector); + mconnector->i2c = i2c; - return connector; -} + return 0; +err_mgag200_i2c_destroy: + mgag200_i2c_destroy(i2c); + return ret; +} int mgag200_modeset_init(struct mga_device *mdev) { struct drm_encoder *encoder = >encoder; - struct drm_connector *connector; + struct drm_connector *connector = >connector.base; int ret; mdev->dev->mode_config.max_width = MGAG200_MAX_FB_WIDTH; @@ -1632,9 +1637,10 @@ int mgag200_modeset_init(struct mga_device *mdev) } encoder->possible_crtcs = 0x1; - connector = mga_vga_init(mdev->dev); - if (!connector) { - DRM_ERROR("mga_vga_init failed\n"); + ret = mgag200_vga_connector_init(mdev); + if (ret) { + drm_err(mdev->dev, + "mga_vga_connector_init() failed, error %d\n", ret); return -1; } -- 2.26.0 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH 13/17] drm/mgag200: Move hiprilvl setting into separate functions
The hiprivlvl settings are now updated in mgag200_g200se_set_hiprilvl() and mgag200_g200ev_set_hiprilvl(). Signed-off-by: Thomas Zimmermann --- drivers/gpu/drm/mgag200/mgag200_mode.c | 98 ++ 1 file changed, 54 insertions(+), 44 deletions(-) diff --git a/drivers/gpu/drm/mgag200/mgag200_mode.c b/drivers/gpu/drm/mgag200/mgag200_mode.c index 6b88c306ff4d7..a04404c5aa769 100644 --- a/drivers/gpu/drm/mgag200/mgag200_mode.c +++ b/drivers/gpu/drm/mgag200/mgag200_mode.c @@ -1118,6 +1118,56 @@ static void mgag200_g200er_reset_tagfifo(struct mga_device *mdev) WREG_SEQ(0x01, seq1); } +static void mgag200_g200se_set_hiprilvl(struct mga_device *mdev, + const struct drm_display_mode *mode, + const struct drm_framebuffer *fb) +{ + unsigned int hiprilvl; + uint8_t crtcext6; + + if (mdev->unique_rev_id >= 0x04) { + hiprilvl = 0; + } else if (mdev->unique_rev_id >= 0x02) { + unsigned int bpp; + unsigned long mb; + + if (fb->format->cpp[0] * 8 > 16) + bpp = 32; + else if (fb->format->cpp[0] * 8 > 8) + bpp = 16; + else + bpp = 8; + + mb = (mode->clock * bpp) / 1000; + if (mb > 3100) + hiprilvl = 0; + else if (mb > 2600) + hiprilvl = 1; + else if (mb > 1900) + hiprilvl = 2; + else if (mb > 1160) + hiprilvl = 3; + else if (mb > 440) + hiprilvl = 4; + else + hiprilvl = 5; + + } else if (mdev->unique_rev_id >= 0x01) { + hiprilvl = 3; + } else { + hiprilvl = 4; + } + + crtcext6 = hiprilvl; /* implicitly sets maxhipri to 0 */ + + WREG_ECRT(0x06, crtcext6); +} + +static void mgag200_g200ev_set_hiprilvl(struct mga_device *mdev) +{ + WREG_ECRT(0x06, 0x00); +} + static int mga_crtc_mode_set(struct drm_crtc *crtc, struct drm_display_mode *mode, struct drm_display_mode *adjusted_mode, @@ -1236,10 +1286,6 @@ static int mga_crtc_mode_set(struct drm_crtc *crtc, if (mdev->type == G200_EW3) WREG_ECRT(0x34, 0x5); - if (mdev->type == G200_EV) { - WREG_ECRT(6, 0); - } - misc = RREG8(MGA_MISC_IN); misc |= MGAREG_MISC_IOADSEL | MGAREG_MISC_RAMMAPEN | @@ -1255,47 +1301,11 @@ static int mga_crtc_mode_set(struct drm_crtc *crtc, if (mdev->type == G200_ER) mgag200_g200er_reset_tagfifo(mdev); + if (IS_G200_SE(mdev)) + mgag200_g200se_set_hiprilvl(mdev, mode, fb); + else if (mdev->type == G200_EV) + mgag200_g200ev_set_hiprilvl(mdev); - if (IS_G200_SE(mdev)) { - if (mdev->unique_rev_id >= 0x04) { - WREG8(MGAREG_CRTCEXT_INDEX, 0x06); - WREG8(MGAREG_CRTCEXT_DATA, 0); - } else if (mdev->unique_rev_id >= 0x02) { - u8 hi_pri_lvl; - u32 bpp; - u32 mb; - - if (fb->format->cpp[0] * 8 > 16) - bpp = 32; - else if (fb->format->cpp[0] * 8 > 8) - bpp = 16; - else - bpp = 8; - - mb = (mode->clock * bpp) / 1000; - if (mb > 3100) - hi_pri_lvl = 0; - else if (mb > 2600) - hi_pri_lvl = 1; - else if (mb > 1900) - hi_pri_lvl = 2; - else if (mb > 1160) - hi_pri_lvl = 3; - else if (mb > 440) - hi_pri_lvl = 4; - else - hi_pri_lvl = 5; - - WREG8(MGAREG_CRTCEXT_INDEX, 0x06); - WREG8(MGAREG_CRTCEXT_DATA, hi_pri_lvl); - } else { - WREG8(MGAREG_CRTCEXT_INDEX, 0x06); - if (mdev->unique_rev_id >= 0x01) - WREG8(MGAREG_CRTCEXT_DATA, 0x03); - else - WREG8(MGAREG_CRTCEXT_DATA, 0x04); - } - } return 0; } -- 2.26.0 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH 04/17] drm/mgag200: Use managed mode-config initialization
Signed-off-by: Thomas Zimmermann --- drivers/gpu/drm/mgag200/mgag200_drv.h | 1 - drivers/gpu/drm/mgag200/mgag200_main.c | 18 - drivers/gpu/drm/mgag200/mgag200_mode.c | 37 -- 3 files changed, 29 insertions(+), 27 deletions(-) diff --git a/drivers/gpu/drm/mgag200/mgag200_drv.h b/drivers/gpu/drm/mgag200/mgag200_drv.h index 09b43a0ff6bbf..4403145e3593c 100644 --- a/drivers/gpu/drm/mgag200/mgag200_drv.h +++ b/drivers/gpu/drm/mgag200/mgag200_drv.h @@ -182,7 +182,6 @@ mgag200_flags_from_driver_data(kernel_ulong_t driver_data) /* mgag200_mode.c */ int mgag200_modeset_init(struct mga_device *mdev); -void mgag200_modeset_fini(struct mga_device *mdev); /* mgag200_main.c */ int mgag200_driver_load(struct drm_device *dev, unsigned long flags); diff --git a/drivers/gpu/drm/mgag200/mgag200_main.c b/drivers/gpu/drm/mgag200/mgag200_main.c index 698fbf31337d4..cf25012f9b6ec 100644 --- a/drivers/gpu/drm/mgag200/mgag200_main.c +++ b/drivers/gpu/drm/mgag200/mgag200_main.c @@ -10,15 +10,8 @@ #include -#include -#include - #include "mgag200_drv.h" -static const struct drm_mode_config_funcs mga_mode_funcs = { - .fb_create = drm_gem_fb_create -}; - static int mga_probe_vram(struct mga_device *mdev, void __iomem *mem) { int offset; @@ -159,14 +152,6 @@ int mgag200_driver_load(struct drm_device *dev, unsigned long flags) if (r) goto err_mm; - drm_mode_config_init(dev); - dev->mode_config.funcs = (void *)_mode_funcs; - if (IS_G200_SE(mdev) && mdev->vram_fb_available < (2048*1024)) - dev->mode_config.preferred_depth = 16; - else - dev->mode_config.preferred_depth = 32; - dev->mode_config.prefer_shadow = 1; - r = mgag200_modeset_init(mdev); if (r) { dev_err(>pdev->dev, "Fatal error during modeset init: %d\n", r); @@ -176,7 +161,6 @@ int mgag200_driver_load(struct drm_device *dev, unsigned long flags) return 0; err_modeset: - drm_mode_config_cleanup(dev); mgag200_mm_fini(mdev); err_mm: dev->dev_private = NULL; @@ -190,8 +174,6 @@ void mgag200_driver_unload(struct drm_device *dev) if (mdev == NULL) return; - mgag200_modeset_fini(mdev); - drm_mode_config_cleanup(dev); mgag200_mm_fini(mdev); dev->dev_private = NULL; } diff --git a/drivers/gpu/drm/mgag200/mgag200_mode.c b/drivers/gpu/drm/mgag200/mgag200_mode.c index eaa3fca7216ac..3d894b37a0812 100644 --- a/drivers/gpu/drm/mgag200/mgag200_mode.c +++ b/drivers/gpu/drm/mgag200/mgag200_mode.c @@ -13,6 +13,7 @@ #include #include +#include #include #include #include @@ -1614,16 +1615,41 @@ static int mgag200_vga_connector_init(struct mga_device *mdev) return ret; } +static const struct drm_mode_config_funcs mgag200_mode_config_funcs = { + .fb_create = drm_gem_fb_create +}; + +static unsigned int mgag200_preferred_depth(struct mga_device *mdev) +{ + if (IS_G200_SE(mdev) && mdev->vram_fb_available < (2048*1024)) + return 16; + else + return 32; +} + int mgag200_modeset_init(struct mga_device *mdev) { + struct drm_device *dev = mdev->dev; struct drm_encoder *encoder = >encoder; struct drm_connector *connector = >connector.base; int ret; - mdev->dev->mode_config.max_width = MGAG200_MAX_FB_WIDTH; - mdev->dev->mode_config.max_height = MGAG200_MAX_FB_HEIGHT; + ret = drmm_mode_config_init(dev); + if (ret) { + drm_err(dev, "drmm_mode_config_init() failed, error %d\n", + ret); + return ret; + } + + dev->mode_config.max_width = MGAG200_MAX_FB_WIDTH; + dev->mode_config.max_height = MGAG200_MAX_FB_HEIGHT; + + dev->mode_config.preferred_depth = mgag200_preferred_depth(mdev); + dev->mode_config.prefer_shadow = 1; + + dev->mode_config.fb_base = mdev->mc.vram_base; - mdev->dev->mode_config.fb_base = mdev->mc.vram_base; + dev->mode_config.funcs = _mode_config_funcs; mga_crtc_init(mdev); @@ -1648,8 +1674,3 @@ int mgag200_modeset_init(struct mga_device *mdev) return 0; } - -void mgag200_modeset_fini(struct mga_device *mdev) -{ - -} -- 2.26.0 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [PATCH] drm/mediatek: cleanup coding style in mediatek a bit
Hi, Bernard: Bernard Zhao 於 2020年4月27日 週一 下午3:53寫道: > > This code change is to make code bit more readable. > Optimise array size align to HDMI macro define. > Add check if len is overange. One patch should just do one thing, but this do three things. So break this into three patches. Regards, Chun-Kuang. > > Signed-off-by: Bernard Zhao > --- > drivers/gpu/drm/mediatek/mtk_hdmi.c | 22 +++--- > 1 file changed, 11 insertions(+), 11 deletions(-) > > diff --git a/drivers/gpu/drm/mediatek/mtk_hdmi.c > b/drivers/gpu/drm/mediatek/mtk_hdmi.c > index ff43a3d80410..40fb5154ed5d 100644 > --- a/drivers/gpu/drm/mediatek/mtk_hdmi.c > +++ b/drivers/gpu/drm/mediatek/mtk_hdmi.c > @@ -311,15 +311,15 @@ static void mtk_hdmi_hw_send_info_frame(struct mtk_hdmi > *hdmi, u8 *buffer, > u8 checksum; > int ctrl_frame_en = 0; > > - frame_type = *buffer; > - buffer += 1; > - frame_ver = *buffer; > - buffer += 1; > - frame_len = *buffer; > - buffer += 1; > - checksum = *buffer; > - buffer += 1; > + frame_type = *buffer++; > + frame_ver = *buffer++; > + frame_len = *buffer++; > + checksum = *buffer++; > frame_data = buffer; > + if ((frame_len + HDMI_INFOFRAME_HEADER_SIZE) > len) { > + dev_err(hdmi->dev, "Wrong frame len: %d\n", frame_len; > + return; > + } > > dev_dbg(hdmi->dev, > > "frame_type:0x%x,frame_ver:0x%x,frame_len:0x%x,checksum:0x%x\n", > @@ -982,7 +982,7 @@ static int mtk_hdmi_setup_avi_infoframe(struct mtk_hdmi > *hdmi, > struct drm_display_mode *mode) > { > struct hdmi_avi_infoframe frame; > - u8 buffer[17]; > + u8 buffer[HDMI_INFOFRAME_HEADER_SIZE + HDMI_AVI_INFOFRAME_SIZE]; > ssize_t err; > > err = drm_hdmi_avi_infoframe_from_display_mode(, > @@ -1008,7 +1008,7 @@ static int mtk_hdmi_setup_spd_infoframe(struct mtk_hdmi > *hdmi, > const char *product) > { > struct hdmi_spd_infoframe frame; > - u8 buffer[29]; > + u8 buffer[HDMI_INFOFRAME_HEADER_SIZE + HDMI_SPD_INFOFRAME_SIZE]; > ssize_t err; > > err = hdmi_spd_infoframe_init(, vendor, product); > @@ -1031,7 +1031,7 @@ static int mtk_hdmi_setup_spd_infoframe(struct mtk_hdmi > *hdmi, > static int mtk_hdmi_setup_audio_infoframe(struct mtk_hdmi *hdmi) > { > struct hdmi_audio_infoframe frame; > - u8 buffer[14]; > + u8 buffer[HDMI_INFOFRAME_HEADER_SIZE + HDMI_AUDIO_INFOFRAME_SIZE]; > ssize_t err; > > err = hdmi_audio_infoframe_init(); > -- > 2.26.2 > > > ___ > Linux-mediatek mailing list > linux-media...@lists.infradead.org > http://lists.infradead.org/mailman/listinfo/linux-mediatek ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [PATCH v2] drm: Fix HDCP failures when SRM fw is missing
On 2020-04-29 at 09:58:16 -0400, Sean Paul wrote: > On Wed, Apr 29, 2020 at 9:50 AM Ramalingam C wrote: > > > > On 2020-04-14 at 15:02:55 -0400, Sean Paul wrote: > > > From: Sean Paul > > > > > > The SRM cleanup in 79643fddd6eb2 ("drm/hdcp: optimizing the srm > > > handling") inadvertently altered the behavior of HDCP auth when > > > the SRM firmware is missing. Before that patch, missing SRM was > > > interpreted as the device having no revoked keys. With that patch, > > > if the SRM fw file is missing we reject _all_ keys. > > > > > > This patch fixes that regression by returning success if the file > > > cannot be found. It also checks the return value from request_srm such > > > that we won't end up trying to parse the ksv list if there is an error > > > fetching it. > > > > > > Fixes: 79643fddd6eb ("drm/hdcp: optimizing the srm handling") > > > Cc: sta...@vger.kernel.org > > > Cc: Ramalingam C > > > Cc: Sean Paul > > > Cc: Maarten Lankhorst > > > Cc: Maxime Ripard > > > Cc: Thomas Zimmermann > > > Cc: David Airlie > > > Cc: Daniel Vetter > > > Cc: dri-devel@lists.freedesktop.org > > > Signed-off-by: Sean Paul > > > > > > Changes in v2: > > > -Noticed a couple other things to clean up > > > --- > > > > > > Sorry for the quick rev, noticed a couple other loose ends that should > > > be cleaned up. > > > > > > drivers/gpu/drm/drm_hdcp.c | 8 +++- > > > 1 file changed, 7 insertions(+), 1 deletion(-) > > > > > > diff --git a/drivers/gpu/drm/drm_hdcp.c b/drivers/gpu/drm/drm_hdcp.c > > > index 7f386adcf872..910108ccaae1 100644 > > > --- a/drivers/gpu/drm/drm_hdcp.c > > > +++ b/drivers/gpu/drm/drm_hdcp.c > > > @@ -241,8 +241,12 @@ static int drm_hdcp_request_srm(struct drm_device > > > *drm_dev, > > > > > > ret = request_firmware_direct(, (const char *)fw_name, > > > drm_dev->dev); > > > - if (ret < 0) > > > + if (ret < 0) { > > > + *revoked_ksv_cnt = 0; > > > + *revoked_ksv_list = NULL; > > These two variables are already initialized by the caller. > > Right now it is, but that's not guaranteed. In the ret == 0 case, it's > pretty common for a caller to assume the called function has > validated/assigned all the function output. Ok. > > > > + ret = 0; > > Missing of this should have been caught by CI. May be CI system always > > having the SRM file from previous execution. Never been removed. IGT > > need a fix to clean the prior SRM files before execution. > > > > CI fix shouldn't block this fix. > > > goto exit; > > > + } > > > > > > if (fw->size && fw->data) > > > ret = drm_hdcp_srm_update(fw->data, fw->size, > > > revoked_ksv_list, > > > @@ -287,6 +291,8 @@ int drm_hdcp_check_ksvs_revoked(struct drm_device > > > *drm_dev, u8 *ksvs, > > > > > > ret = drm_hdcp_request_srm(drm_dev, _ksv_list, > > > _ksv_cnt); > > > + if (ret) > > > + return ret; > > This error code also shouldn't effect the caller(i915) > > Why not? I'd assume an invalid SRM revocation list should probably be > treated as failure? IMHO invalid SRM revocation need not be treated as HDCP authentication failure. First of all SRM need not supplied by all players. and incase, supplied SRM is not as per the spec, then we dont have any list of revoked ID. with this I dont think we need to fail the HDCP authentication. Until we have valid list of revoked IDs from SRM, and the receiver ID is matching to one of the revoked IDs, I wouldn't want to fail the HDCP authentication. -Ram > > > > hence pushed a > > change https://patchwork.freedesktop.org/series/76730/ > > > > With these addresed. > > > > LGTM. > > > > Reviewed-by: Ramalingam C > > > > > > /* revoked_ksv_cnt will be zero when above function failed */ > > > for (i = 0; i < revoked_ksv_cnt; i++) > > > -- > > > Sean Paul, Software Engineer, Google / Chromium OS > > > ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [PATCH v3 05/17] drm/msm/dpu: Use OPP API to set clk/perf state
On 4/29/2020 5:44 AM, Matthias Kaehlcke wrote: On Tue, Apr 28, 2020 at 07:02:53PM +0530, Rajendra Nayak wrote: On some qualcomm platforms DPU needs to express a perforamnce state requirement on a power domain depennding on the clock rates. Use OPP table from DT to register with OPP framework and use dev_pm_opp_set_rate() to set the clk/perf state. Signed-off-by: Rajendra Nayak Cc: Rob Clark Cc: Sean Paul Cc: dri-devel@lists.freedesktop.org --- drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.c | 3 ++- drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c | 25 - drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h | 4 3 files changed, 30 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.c index 11f2beb..fe5717df 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.c @@ -7,6 +7,7 @@ #include #include #include +#include #include #include #include @@ -239,7 +240,7 @@ static int _dpu_core_perf_set_core_clk_rate(struct dpu_kms *kms, u64 rate) rate = core_clk->max_rate; core_clk->rate = rate; - return msm_dss_clk_set_rate(core_clk, 1); + return dev_pm_opp_set_rate(>pdev->dev, core_clk->rate); } static u64 _dpu_core_perf_get_core_clk_rate(struct dpu_kms *kms) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c index ce19f1d..2f53bbf 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c @@ -10,6 +10,7 @@ #include #include #include +#include #include #include @@ -1033,11 +1034,23 @@ static int dpu_bind(struct device *dev, struct device *master, void *data) if (!dpu_kms) return -ENOMEM; + dpu_kms->opp_table = dev_pm_opp_set_clkname(dev, "core"); + if (IS_ERR(dpu_kms->opp_table)) + return PTR_ERR(dpu_kms->opp_table); + /* OPP table is optional */ + ret = dev_pm_opp_of_add_table(dev); + if (!ret) { + dpu_kms->has_opp_table = true; + } else if (ret != -ENODEV) { + dev_err(dev, "Invalid OPP table in Device tree\n"); nit: s/Device/device/ ? uber-nit: s/Invalid/invalid/ most log messages in this file start with a lower case letter, except for acronyms/register names please also change it in the other drivers unless you disagree. Sure, will do. Thanks. + return ret; + } + mp = _kms->mp; ret = msm_dss_parse_clock(pdev, mp); if (ret) { DPU_ERROR("failed to parse clocks, ret=%d\n", ret); - return ret; + goto err; } platform_set_drvdata(pdev, dpu_kms); @@ -1051,6 +1064,11 @@ static int dpu_bind(struct device *dev, struct device *master, void *data) priv->kms = _kms->base; return ret; +err: + if (dpu_kms->has_opp_table) + dev_pm_opp_of_remove_table(dev); + dev_pm_opp_put_clkname(dpu_kms->opp_table); + return ret; } static void dpu_unbind(struct device *dev, struct device *master, void *data) @@ -1059,6 +1077,9 @@ static void dpu_unbind(struct device *dev, struct device *master, void *data) struct dpu_kms *dpu_kms = platform_get_drvdata(pdev); struct dss_module_power *mp = _kms->mp; + if (dpu_kms->has_opp_table) + dev_pm_opp_of_remove_table(dev); + dev_pm_opp_put_clkname(dpu_kms->opp_table); msm_dss_put_clk(mp->clk_config, mp->num_clk); devm_kfree(>dev, mp->clk_config); mp->num_clk = 0; @@ -1090,6 +,8 @@ static int __maybe_unused dpu_runtime_suspend(struct device *dev) struct dpu_kms *dpu_kms = platform_get_drvdata(pdev); struct dss_module_power *mp = _kms->mp; + /* Drop the performance state vote */ + dev_pm_opp_set_rate(dev, 0); rc = msm_dss_enable_clk(mp->clk_config, mp->num_clk, false); if (rc) DPU_ERROR("clock disable failed rc:%d\n", rc); diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h index 211f5de9..2a52e4e 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h @@ -128,6 +128,10 @@ struct dpu_kms { struct platform_device *pdev; bool rpm_enabled; + + struct opp_table *opp_table; + bool has_opp_table; + struct dss_module_power mp; /* reference count bandwidth requests, so we know when we can Reviewed-by: Matthias Kaehlcke -- QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [PATCH v3 -next] drm/mediatek: Fix Kconfig warning
Hi, YueHaibing: YueHaibing 於 2020年4月29日 週三 下午3:14寫道: > > WARNING: unmet direct dependencies detected for MTK_MMSYS > Depends on [n]: (ARCH_MEDIATEK [=y] || COMPILE_TEST [=n]) && > COMMON_CLK_MT8173_MMSYS [=n] > Selected by [y]: > - DRM_MEDIATEK [=y] && HAS_IOMEM [=y] && DRM [=y] && (ARCH_MEDIATEK [=y] || > ARM && COMPILE_TEST [=n]) && COMMON_CLK [=y] && HAVE_ARM_SMCCC [=y] && OF [=y] > > Make DRM_MEDIATEK depend on MTK_MMSYS to fix this. Reviewed-by: Chun-Kuang Hu > > Fixes: 2c758e301ed9 ("soc / drm: mediatek: Move routing control to mmsys > device") > Signed-off-by: YueHaibing > --- > v3: make DRM_MEDIATEK depends on MTK_MMSYS > v2: select COMMON_CLK_MT8173_MMSYS instead of adding DRM_MEDIATEK dependency > --- > drivers/gpu/drm/mediatek/Kconfig | 2 +- > 1 file changed, 1 insertion(+), 1 deletion(-) > > diff --git a/drivers/gpu/drm/mediatek/Kconfig > b/drivers/gpu/drm/mediatek/Kconfig > index c420f5a3d33b..aa74aac3cbcc 100644 > --- a/drivers/gpu/drm/mediatek/Kconfig > +++ b/drivers/gpu/drm/mediatek/Kconfig > @@ -6,12 +6,12 @@ config DRM_MEDIATEK > depends on COMMON_CLK > depends on HAVE_ARM_SMCCC > depends on OF > + depends on MTK_MMSYS > select DRM_GEM_CMA_HELPER > select DRM_KMS_HELPER > select DRM_MIPI_DSI > select DRM_PANEL > select MEMORY > - select MTK_MMSYS > select MTK_SMI > select VIDEOMODE_HELPERS > help > -- > 2.17.1 > > ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [PATCH 02/10] drm: Add backlight helper
Hi Noralf, On 4/29/20 2:48 PM, Noralf Trønnes wrote: This adds a function that creates a backlight device for a connector. It does not deal with the KMS backlight ABI proposition[1] to add a connector property. It only takes the current best practise to standardise the creation of a backlight device for DRM drivers while we wait for the property. The brightness value is set using a connector state variable and an atomic commit. I have looked through some of the backlight users and this is what I've found: GNOME [2] - Brightness range: 0-100 Scale: Assumes perceptual I'm afraid that this is an incaccurate view of how GNOME handles the brightness. gnome-settings-daemon (g-s-d) exports a DBUS property which has a range of 0 - 100%. But it also offers step-up and step-down DBUS methods which are used for handling brightness hotkey presses. This is important because g-s-d internally also keeps a step_size variable which depends on the brightness_max value of the sysfs backlight interface, like this: BRIGHTNESS_STEP_AMOUNT(max) ((max) < 20 ? 1 : (max) / 20) This is important because some older laptops where we depend on the vendor specific ACPI method (from e.g. dell-laptop or thinkpad_acpi) there are only 8 levels. So if g-s-d where to simply fake a 1-100 range and would leave the stepping up to the DBus API user and that user would want 20 steps, so 5 % per step, then the user would get Start -> 100% -> level 8 Press down -> 95% -> level 7 Press down -> 90% -> level 7 *no change* etc. Somewhat related on some embedded ARM devices there are tricks where when the entire scene being rendered does not use 100% white as color, the entire scene has all its rgb values upscaled (too a curve) so that the brightest colors do hit 100% of one of r/g/b, combined with dimming the backlight a bit to save power. As you can imagine for tricks like these you want as much backlight control precision as possible. So any backlight infra we add must expose the true range of the backlight control and not normalize it to a 0-100 range. So sorry, but nack for the current version because of the hardcoding of the range. Also the scale really should be specified by the driver, or be hardcoded to BACKLIGHT_SCALE_UNKNOWN for now. In many cases we do not really know. But for e.g. the acpi_video firmware backlight interface a good guess is that it actually represents a perceptual scale rather then controlling the wattage. Where as the native i915 backlight interface really is controlling the wattage without any perceptual correction. Another problem with your proposal is that it seems to assume that the backlight is controlled by the drm/kms driver. On x86 we have atleast 3 different drivers for the backlight: 1) The i915 (or amd/nouveau) native driver which more or less directly pokes the PWM controller of the GPU. 2) The ACPI video standard backlight interface 3) Vendor specific ACPI interfaces from older laptops ATM we always register 1. which could remain unchanged with your code and then also register 2/3 if we (the kernel) think that will work better (*) and then rely on userspace prefering these (they have a different backlight_type) over 1. Ideally any infra we add will also offer the option to tie 2. or 3. to the connector... Regards, Hans *) e.g. it will work while the others will not work at all Avoids setting the sysfs brightness value to zero if max_brightness >= 99. Can connect connector and backlight using the sysfs device. KDE [3] --- Brightness range: 0-100 Scale: Assumes perceptual Weston [4] -- Brightness range: 0-255 Scale: Assumes perceptual Chromium OS [5] --- Brightness range: 0-100 Scale: Depends on the sysfs file 'scale' which is a recent addition (2019) xserver [6] --- Brightness range: 0-x (driver specific) (1 is minimum, 0 is OFF) Scale: Assumes perceptual The builtin modesetting driver[7] does not support Backlight, Intel[8] does. [1] https://lore.kernel.org/dri-devel/4b17ba08-39f3-57dd-5aad-d37d844b0...@linux.intel.com/ [2] https://gitlab.gnome.org/GNOME/gnome-settings-daemon/-/blob/master/plugins/power/gsd-backlight.c [3] https://github.com/KDE/powerdevil/blob/master/daemon/backends/upower/backlighthelper.cpp [4] https://gitlab.freedesktop.org/wayland/weston/-/blob/master/libweston/backend-drm/drm.c [5] https://chromium.googlesource.com/chromiumos/platform2/+/refs/heads/master/power_manager/powerd/system/internal_backlight.cc [6] https://github.com/freedesktop/xorg-randrproto/blob/master/randrproto.txt [7] https://gitlab.freedesktop.org/xorg/xserver/-/blob/master/hw/xfree86/drivers/modesetting/drmmode_display.c [8] https://gitlab.freedesktop.org/xorg/driver/xf86-video-intel/-/blob/master/src/backlight.c Cc: Hans de Goede Cc: Jani Nikula Cc: Martin Peres Cc: Daniel Thompson Signed-off-by: Noralf Trønnes --- Documentation/gpu/drm-kms-helpers.rst | 6 + drivers/gpu/drm/Kconfig| 7 ++
Re: [PATCH v3 05/17] drm/msm/dpu: Use OPP API to set clk/perf state
On 4/28/2020 10:02 PM, Rob Clark wrote: On Tue, Apr 28, 2020 at 6:39 AM Rajendra Nayak wrote: On some qualcomm platforms DPU needs to express a perforamnce state s/perforamnce/performance/ requirement on a power domain depennding on the clock rates. s/depennding/depending/ Use OPP table from DT to register with OPP framework and use dev_pm_opp_set_rate() to set the clk/perf state. Signed-off-by: Rajendra Nayak Cc: Rob Clark Cc: Sean Paul Cc: dri-devel@lists.freedesktop.org --- drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.c | 3 ++- drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c | 25 - drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h | 4 3 files changed, 30 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.c index 11f2beb..fe5717df 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.c @@ -7,6 +7,7 @@ #include #include #include +#include #include #include #include @@ -239,7 +240,7 @@ static int _dpu_core_perf_set_core_clk_rate(struct dpu_kms *kms, u64 rate) rate = core_clk->max_rate; core_clk->rate = rate; - return msm_dss_clk_set_rate(core_clk, 1); + return dev_pm_opp_set_rate(>pdev->dev, core_clk->rate); I think this leaves msm_dss_clk_set_rate() unused now? yup, I didn't realise, I will get rid of it when I respin. Other than that, Reviewed-by: Rob Clark Thanks. } static u64 _dpu_core_perf_get_core_clk_rate(struct dpu_kms *kms) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c index ce19f1d..2f53bbf 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c @@ -10,6 +10,7 @@ #include #include #include +#include #include #include @@ -1033,11 +1034,23 @@ static int dpu_bind(struct device *dev, struct device *master, void *data) if (!dpu_kms) return -ENOMEM; + dpu_kms->opp_table = dev_pm_opp_set_clkname(dev, "core"); + if (IS_ERR(dpu_kms->opp_table)) + return PTR_ERR(dpu_kms->opp_table); + /* OPP table is optional */ + ret = dev_pm_opp_of_add_table(dev); + if (!ret) { + dpu_kms->has_opp_table = true; + } else if (ret != -ENODEV) { + dev_err(dev, "Invalid OPP table in Device tree\n"); + return ret; + } + mp = _kms->mp; ret = msm_dss_parse_clock(pdev, mp); if (ret) { DPU_ERROR("failed to parse clocks, ret=%d\n", ret); - return ret; + goto err; } platform_set_drvdata(pdev, dpu_kms); @@ -1051,6 +1064,11 @@ static int dpu_bind(struct device *dev, struct device *master, void *data) priv->kms = _kms->base; return ret; +err: + if (dpu_kms->has_opp_table) + dev_pm_opp_of_remove_table(dev); + dev_pm_opp_put_clkname(dpu_kms->opp_table); + return ret; } static void dpu_unbind(struct device *dev, struct device *master, void *data) @@ -1059,6 +1077,9 @@ static void dpu_unbind(struct device *dev, struct device *master, void *data) struct dpu_kms *dpu_kms = platform_get_drvdata(pdev); struct dss_module_power *mp = _kms->mp; + if (dpu_kms->has_opp_table) + dev_pm_opp_of_remove_table(dev); + dev_pm_opp_put_clkname(dpu_kms->opp_table); msm_dss_put_clk(mp->clk_config, mp->num_clk); devm_kfree(>dev, mp->clk_config); mp->num_clk = 0; @@ -1090,6 +,8 @@ static int __maybe_unused dpu_runtime_suspend(struct device *dev) struct dpu_kms *dpu_kms = platform_get_drvdata(pdev); struct dss_module_power *mp = _kms->mp; + /* Drop the performance state vote */ + dev_pm_opp_set_rate(dev, 0); rc = msm_dss_enable_clk(mp->clk_config, mp->num_clk, false); if (rc) DPU_ERROR("clock disable failed rc:%d\n", rc); diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h index 211f5de9..2a52e4e 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h @@ -128,6 +128,10 @@ struct dpu_kms { struct platform_device *pdev; bool rpm_enabled; + + struct opp_table *opp_table; + bool has_opp_table; + struct dss_module_power mp; /* reference count bandwidth requests, so we know when we can -- QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation -- QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation ___ dri-devel mailing list dri-devel@lists.freedesktop.org
Re: [PATCH v2] drm/panel: simple: Support reset GPIOs
Hi Sam, you've asked in another thread [1] if there is any known simple panel that requires a reset. We have a Densitron DMT070WSNLCMI-1E Panel (compatible to avic,tm070ddh03) with some reset timing requirements, [2] Page 20. So it would be nice to see this patch accepted. [1] https://patchwork.kernel.org/patch/11292207/ [2] https://www.densitron.com/sites/default/files/2019-09/DMT070WSNLCMI-1E%20Rev%20A.pdf Regards, Wadim On 06.01.20 10:10, Miquel Raynal wrote: > Hi Sam, > > Sam Ravnborg wrote on Thu, 2 Jan 2020 18:27:00 +0100: > >> Hi Miquel >> >> On Tue, Dec 24, 2019 at 03:21:34PM +0100, Miquel Raynal wrote: >>> The panel common bindings provide a gpios-reset property. Let's >>> support it in the simple driver. >>> >>> Two fields are added to the panel description structure: the time to >>> assert the reset and the time to wait right after before starting to >>> interact with it in any manner. In case these default values are not >>> filled but the GPIO is present in the DT, default values are applied. >> Wehn we discussed this the last time you wrote: >> >> """ >> my hardware is: >> >> LVDS IP <--> LVDS to RGB bridge <> Panel >> >> While there is a simple "RGB to LVDS" bridge driver, there is none >> doing the work the other way around. In my case, the bridge has a reset >> pin. >> >> As until now there is no way to represent the "LVDS to RGB" bridge and >> because the bindings already document such reset pin, I decided to add >> support for it in the simple panel driver. >> """ >> >> Based on the information provided it seems that the correct way is to >> add a "LVDS to RGB bridge" and then let the bridge handle the reset >> functionality. > This I agree, but we are talking about my current situation. > >> It is obviously much more code to do it this way but then >> other panels using the same type of brigde have the >> same functionality without adding bridge functionality to the panel. > This, I do not fully agree as bindings for the panel reset already > exist and we could have a reset on both: the bridge and the panel. > I choose to use a wrong (private) DT representation because I am not > willing to add an LVDS->RGB bridge: as you say, it is much more work to > do. But, IMHO, this is not related to the patch. If you consider this > patch wrong because a panel cannot have a reset, then it should be > stated clearly and maybe removed from the bindings? > > Anyway if you think this change can't be useful, let's put it aside. > > Thanks for your time, > Miquèl > > ___ > dri-devel mailing list > dri-devel@lists.freedesktop.org > https://lists.freedesktop.org/mailman/listinfo/dri-devel ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [PATCH v2] drm: Fix HDCP failures when SRM fw is missing
On Wed, Apr 29, 2020 at 9:50 AM Ramalingam C wrote: > > On 2020-04-14 at 15:02:55 -0400, Sean Paul wrote: > > From: Sean Paul > > > > The SRM cleanup in 79643fddd6eb2 ("drm/hdcp: optimizing the srm > > handling") inadvertently altered the behavior of HDCP auth when > > the SRM firmware is missing. Before that patch, missing SRM was > > interpreted as the device having no revoked keys. With that patch, > > if the SRM fw file is missing we reject _all_ keys. > > > > This patch fixes that regression by returning success if the file > > cannot be found. It also checks the return value from request_srm such > > that we won't end up trying to parse the ksv list if there is an error > > fetching it. > > > > Fixes: 79643fddd6eb ("drm/hdcp: optimizing the srm handling") > > Cc: sta...@vger.kernel.org > > Cc: Ramalingam C > > Cc: Sean Paul > > Cc: Maarten Lankhorst > > Cc: Maxime Ripard > > Cc: Thomas Zimmermann > > Cc: David Airlie > > Cc: Daniel Vetter > > Cc: dri-devel@lists.freedesktop.org > > Signed-off-by: Sean Paul > > > > Changes in v2: > > -Noticed a couple other things to clean up > > --- > > > > Sorry for the quick rev, noticed a couple other loose ends that should > > be cleaned up. > > > > drivers/gpu/drm/drm_hdcp.c | 8 +++- > > 1 file changed, 7 insertions(+), 1 deletion(-) > > > > diff --git a/drivers/gpu/drm/drm_hdcp.c b/drivers/gpu/drm/drm_hdcp.c > > index 7f386adcf872..910108ccaae1 100644 > > --- a/drivers/gpu/drm/drm_hdcp.c > > +++ b/drivers/gpu/drm/drm_hdcp.c > > @@ -241,8 +241,12 @@ static int drm_hdcp_request_srm(struct drm_device > > *drm_dev, > > > > ret = request_firmware_direct(, (const char *)fw_name, > > drm_dev->dev); > > - if (ret < 0) > > + if (ret < 0) { > > + *revoked_ksv_cnt = 0; > > + *revoked_ksv_list = NULL; > These two variables are already initialized by the caller. Right now it is, but that's not guaranteed. In the ret == 0 case, it's pretty common for a caller to assume the called function has validated/assigned all the function output. > > + ret = 0; > Missing of this should have been caught by CI. May be CI system always > having the SRM file from previous execution. Never been removed. IGT > need a fix to clean the prior SRM files before execution. > > CI fix shouldn't block this fix. > > goto exit; > > + } > > > > if (fw->size && fw->data) > > ret = drm_hdcp_srm_update(fw->data, fw->size, > > revoked_ksv_list, > > @@ -287,6 +291,8 @@ int drm_hdcp_check_ksvs_revoked(struct drm_device > > *drm_dev, u8 *ksvs, > > > > ret = drm_hdcp_request_srm(drm_dev, _ksv_list, > > _ksv_cnt); > > + if (ret) > > + return ret; > This error code also shouldn't effect the caller(i915) Why not? I'd assume an invalid SRM revocation list should probably be treated as failure? > hence pushed a > change https://patchwork.freedesktop.org/series/76730/ > > With these addresed. > > LGTM. > > Reviewed-by: Ramalingam C > > > > /* revoked_ksv_cnt will be zero when above function failed */ > > for (i = 0; i < revoked_ksv_cnt; i++) > > -- > > Sean Paul, Software Engineer, Google / Chromium OS > > ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [PATCH v3] backlight: lms283gf05: Convert to GPIO descriptors
On Wed, Apr 29, 2020 at 02:43:54PM +0200, Linus Walleij wrote: > This converts the lms283gf05 backlight driver to use GPIO > descriptors and switches the single PXA Palm Z2 device > over to defining these. > > Since the platform data was only used to convey GPIO > information we can delete the platform data header. > > Notice that we define the proper active low semantics in > the board file GPIO descriptor table (active low) and > assert the reset line by bringing it to "1" (asserted). > > Cc: Marek Vasut > Cc: Daniel Mack > Cc: Haojian Zhuang > Cc: Robert Jarzmik > Signed-off-by: Linus Walleij > --- > ChangeLog v2->v3: > - Fix a use-before-allocated bug discovered by compile tests. > - Remove unused ret variable as autobuilders complained. > ChangeLog v1->v2: > - Bring up the GPIO de-asserted in probe() > > Marek: I saw this was written by you, are you regularly > testing the Z2 device? > --- > arch/arm/mach-pxa/z2.c | 12 +--- > drivers/video/backlight/lms283gf05.c | 42 +++- > include/linux/spi/lms283gf05.h | 16 --- > 3 files changed, 24 insertions(+), 46 deletions(-) > delete mode 100644 include/linux/spi/lms283gf05.h > > diff --git a/drivers/video/backlight/lms283gf05.c > b/drivers/video/backlight/lms283gf05.c > index 0e45685bcc1c..529c415eb03b 100644 > --- a/drivers/video/backlight/lms283gf05.c > +++ b/drivers/video/backlight/lms283gf05.c > @@ -150,24 +147,17 @@ static struct lcd_ops lms_ops = { > static int lms283gf05_probe(struct spi_device *spi) > { > struct lms283gf05_state *st; > - struct lms283gf05_pdata *pdata = dev_get_platdata(>dev); > struct lcd_device *ld; > - int ret = 0; > - > - if (pdata != NULL) { > - ret = devm_gpio_request_one(>dev, pdata->reset_gpio, > - GPIOF_DIR_OUT | (!pdata->reset_inverted ? > - GPIOF_INIT_HIGH : GPIOF_INIT_LOW), > - "LMS283GF05 RESET"); > - if (ret) > - return ret; > - } > > st = devm_kzalloc(>dev, sizeof(struct lms283gf05_state), > GFP_KERNEL); > if (st == NULL) > return -ENOMEM; > > + st->reset = gpiod_get_optional(>dev, "reset", GPIOD_OUT_LOW); > + if (st->reset) > + gpiod_set_consumer_name(st->reset, "LMS283GF05 RESET"); > + Sorry, I should have picked this up before but shouldn't st->reset have an IS_ERR() check. There are certainly no other examples of this API within the kernel that are not followed by an IS_ERR() check! In fact I understood that the gpiod API is intended to tolerate NULLs so I would have expected this code to be: st->reset = gpiod_get_optional(>dev, "reset", GPIOD_OUT_LOW); if (IS_ERR(st->reset)) return PTR_ERR(st->reset); gpiod_set_consumer_name(st->reset, "LMS283GF05 RESET"); > ld = devm_lcd_device_register(>dev, "lms283gf05", >dev, st, > _ops); > if (IS_ERR(ld)) Daniel. > ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [PATCH v2] drm: Fix HDCP failures when SRM fw is missing
On 2020-04-14 at 15:02:55 -0400, Sean Paul wrote: > From: Sean Paul > > The SRM cleanup in 79643fddd6eb2 ("drm/hdcp: optimizing the srm > handling") inadvertently altered the behavior of HDCP auth when > the SRM firmware is missing. Before that patch, missing SRM was > interpreted as the device having no revoked keys. With that patch, > if the SRM fw file is missing we reject _all_ keys. > > This patch fixes that regression by returning success if the file > cannot be found. It also checks the return value from request_srm such > that we won't end up trying to parse the ksv list if there is an error > fetching it. > > Fixes: 79643fddd6eb ("drm/hdcp: optimizing the srm handling") > Cc: sta...@vger.kernel.org > Cc: Ramalingam C > Cc: Sean Paul > Cc: Maarten Lankhorst > Cc: Maxime Ripard > Cc: Thomas Zimmermann > Cc: David Airlie > Cc: Daniel Vetter > Cc: dri-devel@lists.freedesktop.org > Signed-off-by: Sean Paul > > Changes in v2: > -Noticed a couple other things to clean up > --- > > Sorry for the quick rev, noticed a couple other loose ends that should > be cleaned up. > > drivers/gpu/drm/drm_hdcp.c | 8 +++- > 1 file changed, 7 insertions(+), 1 deletion(-) > > diff --git a/drivers/gpu/drm/drm_hdcp.c b/drivers/gpu/drm/drm_hdcp.c > index 7f386adcf872..910108ccaae1 100644 > --- a/drivers/gpu/drm/drm_hdcp.c > +++ b/drivers/gpu/drm/drm_hdcp.c > @@ -241,8 +241,12 @@ static int drm_hdcp_request_srm(struct drm_device > *drm_dev, > > ret = request_firmware_direct(, (const char *)fw_name, > drm_dev->dev); > - if (ret < 0) > + if (ret < 0) { > + *revoked_ksv_cnt = 0; > + *revoked_ksv_list = NULL; These two variables are already initialized by the caller. > + ret = 0; Missing of this should have been caught by CI. May be CI system always having the SRM file from previous execution. Never been removed. IGT need a fix to clean the prior SRM files before execution. CI fix shouldn't block this fix. > goto exit; > + } > > if (fw->size && fw->data) > ret = drm_hdcp_srm_update(fw->data, fw->size, revoked_ksv_list, > @@ -287,6 +291,8 @@ int drm_hdcp_check_ksvs_revoked(struct drm_device > *drm_dev, u8 *ksvs, > > ret = drm_hdcp_request_srm(drm_dev, _ksv_list, > _ksv_cnt); > + if (ret) > + return ret; This error code also shouldn't effect the caller(i915) hence pushed a change https://patchwork.freedesktop.org/series/76730/ With these addresed. LGTM. Reviewed-by: Ramalingam C > > /* revoked_ksv_cnt will be zero when above function failed */ > for (i = 0; i < revoked_ksv_cnt; i++) > -- > Sean Paul, Software Engineer, Google / Chromium OS > ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH] drm/i915/hdcp: Fix the return handling of drm_hdcp_check_ksvs_revoked
drm_hdcp_check_ksvs_revoked() returns the number of revoked keys and error codes when the SRM parsing is failed. Errors in SRM parsing can't affect the HDCP auth, hence with this patch, I915 will look out for revoked key count alone. Signed-off-by: Ramalingam C cc: Sean Paul --- drivers/gpu/drm/i915/display/intel_hdcp.c | 8 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_hdcp.c b/drivers/gpu/drm/i915/display/intel_hdcp.c index 2cbc4619b4ce..96bf6def9830 100644 --- a/drivers/gpu/drm/i915/display/intel_hdcp.c +++ b/drivers/gpu/drm/i915/display/intel_hdcp.c @@ -576,7 +576,7 @@ int intel_hdcp_auth_downstream(struct intel_connector *connector) goto err; if (drm_hdcp_check_ksvs_revoked(_priv->drm, ksv_fifo, - num_downstream)) { + num_downstream) > 0) { drm_err(_priv->drm, "Revoked Ksv(s) in ksv_fifo\n"); ret = -EPERM; goto err; @@ -682,7 +682,7 @@ static int intel_hdcp_auth(struct intel_connector *connector) if (ret < 0) return ret; - if (drm_hdcp_check_ksvs_revoked(_priv->drm, bksv.shim, 1)) { + if (drm_hdcp_check_ksvs_revoked(_priv->drm, bksv.shim, 1) > 0) { drm_err(_priv->drm, "BKSV is revoked\n"); return -EPERM; } @@ -1283,7 +1283,7 @@ static int hdcp2_authentication_key_exchange(struct intel_connector *connector) if (drm_hdcp_check_ksvs_revoked(_priv->drm, msgs.send_cert.cert_rx.receiver_id, - 1)) { + 1) > 0) { drm_err(_priv->drm, "Receiver ID is revoked\n"); return -EPERM; } @@ -1484,7 +1484,7 @@ int hdcp2_authenticate_repeater_topology(struct intel_connector *connector) HDCP_2_2_DEV_COUNT_LO(rx_info[1])); if (drm_hdcp_check_ksvs_revoked(_priv->drm, msgs.recvid_list.receiver_ids, - device_cnt)) { + device_cnt) > 0) { drm_err(_priv->drm, "Revoked receiver ID(s) is in list\n"); return -EPERM; } -- 2.20.1 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [PATCH] [v2] amdgpu: fix gcc-4.8 build warnings
On 2020-04-29 5:20 a.m., Arnd Bergmann wrote: Older compilers warn about initializers with incorrect curly braces: drivers/gpu/drm/drm_dp_mst_topology.c: In function 'drm_dp_mst_dsc_aux_for_port': drivers/gpu/drm/drm_dp_mst_topology.c:5497:9: error: missing braces around initializer [-Werror=missing-braces] struct drm_dp_desc desc = { 0 }; ^ Change all instances in the amd gpu driver to using the GNU empty initializer extension. These should actually be memset - instead of GCC complaining, it'll be clang instead. Regards, Nicholas Kazlauskas Reviewed-by: Rodrigo Siqueira Signed-off-by: Arnd Bergmann --- v2: some context changes linux-next stopped yesterday's patch from applying today. --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 2 +- drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c| 2 +- drivers/gpu/drm/amd/display/dc/clk_mgr/dcn21/rn_clk_mgr.c | 2 +- drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c | 6 +++--- drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hubp.c | 6 +++--- drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c | 2 +- drivers/gpu/drm/amd/display/dc/dcn21/dcn21_hubp.c | 6 +++--- 7 files changed, 13 insertions(+), 13 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 7f4417981bff..81ce3103d751 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -8695,7 +8695,7 @@ bool amdgpu_dm_psr_enable(struct dc_stream_state *stream) { struct dc_link *link = stream->link; unsigned int vsync_rate_hz = 0; - struct dc_static_screen_params params = {0}; + struct dc_static_screen_params params = { }; /* Calculate number of static frames before generating interrupt to * enter PSR. */ diff --git a/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c b/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c index 37fa7b48250e..5484a316eaa8 100644 --- a/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c +++ b/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c @@ -294,7 +294,7 @@ static enum bp_result bios_parser_get_i2c_info(struct dc_bios *dcb, struct atom_display_object_path_v2 *object; struct atom_common_record_header *header; struct atom_i2c_record *record; - struct atom_i2c_record dummy_record = {0}; + struct atom_i2c_record dummy_record = { }; struct bios_parser *bp = BP_FROM_DCB(dcb); if (!info) diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn21/rn_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn21/rn_clk_mgr.c index 24c5765890fa..ee3ef5094fd1 100644 --- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn21/rn_clk_mgr.c +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn21/rn_clk_mgr.c @@ -698,7 +698,7 @@ void rn_clk_mgr_construct( struct dccg *dccg) { struct dc_debug_options *debug = >dc->debug; - struct dpm_clocks clock_table = { 0 }; + struct dpm_clocks clock_table = { }; clk_mgr->base.ctx = ctx; clk_mgr->base.funcs = _funcs; diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c index 9ef9e50a34fa..7cbfe740a947 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c @@ -2683,9 +2683,9 @@ static void dp_test_send_link_test_pattern(struct dc_link *link) static void dp_test_get_audio_test_data(struct dc_link *link, bool disable_video) { - union audio_test_modedpcd_test_mode = {0}; - struct audio_test_pattern_type dpcd_pattern_type = {0}; - union audio_test_pattern_period dpcd_pattern_period[AUDIO_CHANNELS_COUNT] = {0}; + union audio_test_modedpcd_test_mode = { }; + struct audio_test_pattern_type dpcd_pattern_type = { }; + union audio_test_pattern_period dpcd_pattern_period[AUDIO_CHANNELS_COUNT] = { }; enum dp_test_pattern test_pattern = DP_TEST_PATTERN_AUDIO_OPERATOR_DEFINED; struct pipe_ctx *pipes = link->dc->current_state->res_ctx.pipe_ctx; diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hubp.c b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hubp.c index 84d7ac5dd206..dfa541f0b0d3 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hubp.c +++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hubp.c @@ -1253,9 +1253,9 @@ void hubp2_validate_dml_output(struct hubp *hubp, struct _vcs_dpi_display_ttu_regs_st *dml_ttu_attr) { struct dcn20_hubp *hubp2 = TO_DCN20_HUBP(hubp); - struct _vcs_dpi_display_rq_regs_st rq_regs = {0}; - struct _vcs_dpi_display_dlg_regs_st dlg_attr = {0}; - struct _vcs_dpi_display_ttu_regs_st ttu_attr = {0}; + struct _vcs_dpi_display_rq_regs_st rq_regs = { }; + struct _vcs_dpi_display_dlg_regs_st dlg_attr = { }; +
Re: [PATCH v2] video: fbdev: controlfb: fix build for COMPILE_TEST=y && PPC_PMAC=y && PPC32=n
Hi Christoph On Wed, Apr 29, 2020 at 05:51:01AM -0700, Christoph Hellwig wrote: > Why do we even bother allocing the driver to compile for !ppc32 > given that it clearly needs ppc-specific infrastructure? The whole > idea of needing magic stubs for the COMPILE_TEST case seems rather > counterproduction. All the usual good arguments. If this driver only builds for 32bit powerpc then we will seldom build it and every time we do some refactoring we risk introducing build errros in this driver that is triggered much later. So a few hacks are preferred to actually make it build. But hacks should not paper over missing abstractions in the general ioremap handlign and such. I recall someone said the other day that drm folks had a tendency to workaround rather than fixing this. So this is "drm folks" reaching out and asking if this is a case where we have a workaround and need a fix? I will - after some testing - apply the fix from Bartlomiej. But would like to know if this is a workarond or a fix. Dropping COMPILE_TEST is not an option as explained above. Sam ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [PATCH v2] drm/meson: add mode selection limits against specific SoC revisions
Hi, On 29/04/2020 00:03, Martin Blumenstingl wrote: > Hi Neil, > > On Tue, Apr 28, 2020 at 11:21 AM Neil Armstrong > wrote: >> >> The Amlogic S805X/Y uses the same die as the S905X, but with more >> limited graphics capabilities. >> >> This adds a soc version detection adding specific limitations on the HDMI >> mode selections. >> >> Here, we limit to HDMI 1.3a max HDMI PHY clock frequency. > for my own education: 1.65GHz from the PLL will be divided down to 165MHz > isn't this more like the limit of HDMI 1.2a? indeed from [1] : ``` HDMI 1.3 / 1.3a: - Higher speed: HDMI 1.3 increases its single-link bandwidth to 340 MHz (10.2 Gbps) to support the demands of future HD display devices, such as higher resolutions, Deep Color and high frame rates. In addition, built into the HDMI 1.3 specification is the technical foundations that will let future versions of HDMI reach significantly higher speeds. ``` So yes, it must be HDMI 1.2a, I'll fixup while applying. > >> Changes sinces v1: >> - Moved frequency check in the vclk code, and also checks DMT modes >> >> Signed-off-by: Neil Armstrong > Acked-by: Martin Blumenstingl > > This looks good to me based on the current limitations of meson_vclk.c > If we switch to CCF based VPU clock rate changes then we should do > this in the clock driver by calling clk_hw_set_rate_range(hdmi_pll, 0, > 1.65GHz) > > The good thing is: we can re-use struct meson_drm_soc_limits even > after switching to CCF. > We will just need to set the max PHY freq using > clk_round_rate(hdmi_pll, ULONG_MAX) Exact ! Neil > > > Martin > [1] https://denon.custhelp.com/app/answers/detail/a_id/192/~/differences-between-hdmi-versions-1.1%2C-1.2%2C-1.3a%2C-1.4-and-2.0%3F ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [PATCH v2] video: fbdev: controlfb: fix build for COMPILE_TEST=y && PPC_PMAC=y && PPC32=n
On 4/29/20 2:51 PM, Christoph Hellwig wrote: > Why do we even bother allocing the driver to compile for !ppc32 > given that it clearly needs ppc-specific infrastructure? The whole > idea of needing magic stubs for the COMPILE_TEST case seems rather > counterproduction. Not a perfect solution but at the cost of 2 ifdefs it allows controlfb driver to be compile tested on any arch. Being able to compile test fbdev device drivers is really useful for me and saves me a lot of time when doing fbdev maintainer duties. Best regards, -- Bartlomiej Zolnierkiewicz Samsung R Institute Poland Samsung Electronics ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [PATCH] sun6i: dsi: fix gcc-4.8
Hi, On Tue 28 Apr 20, 23:50, Arnd Bergmann wrote: > Older compilers warn about initializers with incorrect curly > braces: > > drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c: In function > 'sun6i_dsi_encoder_enable': > drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c:720:8: error: missing braces around > initializer [-Werror=missing-braces] > union phy_configure_opts opts = { 0 }; > ^ > drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c:720:8: error: (near initialization for > 'opts.mipi_dphy') [-Werror=missing-braces] > > Use the GNU empty initializer extension to avoid this. Looks good to me: Reviewed-by: Paul Kocialkowski But maybe use the drm/sun4i: dsi: prefix instead (granted, it wasn't used in the commit being fixed). Cheers, Paul > Fixes: bb3b6fcb6849 ("sun6i: dsi: Convert to generic phy handling") > Signed-off-by: Arnd Bergmann > --- > drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c | 2 +- > 1 file changed, 1 insertion(+), 1 deletion(-) > > diff --git a/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c > b/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c > index f6c67dd87a05..aa67cb037e9d 100644 > --- a/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c > +++ b/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c > @@ -718,7 +718,7 @@ static void sun6i_dsi_encoder_enable(struct drm_encoder > *encoder) > struct drm_display_mode *mode = >crtc->state->adjusted_mode; > struct sun6i_dsi *dsi = encoder_to_sun6i_dsi(encoder); > struct mipi_dsi_device *device = dsi->device; > - union phy_configure_opts opts = { 0 }; > + union phy_configure_opts opts = { }; > struct phy_configure_opts_mipi_dphy *cfg = _dphy; > u16 delay; > int err; > -- > 2.26.0 > -- Paul Kocialkowski, Bootlin Embedded Linux and kernel engineering https://bootlin.com signature.asc Description: PGP signature ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH 08/10] drm: Add Generic USB Display driver
This adds a generic USB display driver with the intention that it can be used with future USB interfaced low end displays/adapters. The Linux gadget device driver will serve as the canonical device implementation. The following DRM properties are supported: - Plane rotation - Connector TV properties There is also support for backlight brightness exposed as a backlight device. Display modes can be made available to the host driver either as DRM display modes or through EDID. If both are present, EDID is just passed on to userspace. Performance is preferred over color depth, so if the device supports RGB565, DRM_CAP_DUMB_PREFERRED_DEPTH will return 16. If the device transfer buffer can't fit an uncompressed framebuffer update, the update is split up into parts that do fit. Optimal user experience is achieved by providing damage reports either by setting FB_DAMAGE_CLIPS on pageflips or calling DRM_IOCTL_MODE_DIRTYFB. LZ4 compression is used if the device supports it. The driver supports a one bit monochrome transfer format: R1. This is not implemented in the gadget driver. It is added in preparation for future monochrome e-ink displays. The driver is MIT licensed to smooth the path for any BSD port of the driver. Signed-off-by: Noralf Trønnes --- MAINTAINERS | 8 + drivers/gpu/drm/Kconfig | 2 + drivers/gpu/drm/Makefile| 1 + drivers/gpu/drm/gud/Kconfig | 14 + drivers/gpu/drm/gud/Makefile| 4 + drivers/gpu/drm/gud/gud_drm_connector.c | 629 drivers/gpu/drm/gud/gud_drm_drv.c | 624 +++ drivers/gpu/drm/gud/gud_drm_internal.h | 66 +++ drivers/gpu/drm/gud/gud_drm_pipe.c | 423 include/drm/gud_drm.h | 356 ++ 10 files changed, 2127 insertions(+) create mode 100644 drivers/gpu/drm/gud/Kconfig create mode 100644 drivers/gpu/drm/gud/Makefile create mode 100644 drivers/gpu/drm/gud/gud_drm_connector.c create mode 100644 drivers/gpu/drm/gud/gud_drm_drv.c create mode 100644 drivers/gpu/drm/gud/gud_drm_internal.h create mode 100644 drivers/gpu/drm/gud/gud_drm_pipe.c create mode 100644 include/drm/gud_drm.h diff --git a/MAINTAINERS b/MAINTAINERS index 08ae8ea76939..bb4609984e9a 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -5282,6 +5282,14 @@ S: Maintained F: drivers/gpu/drm/panel/panel-feiyang-fy07024di26a30d.c F: Documentation/devicetree/bindings/display/panel/feiyang,fy07024di26a30d.txt +DRM DRIVER FOR GENERIC USB DISPLAY +M: Noralf Trønnes +S: Maintained +W: https://github.com/notro/gud/wiki +T: git git://anongit.freedesktop.org/drm/drm-misc +F: drivers/gpu/drm/gud/ +F: include/drm/gud_drm.h + DRM DRIVER FOR GRAIN MEDIA GM12U320 PROJECTORS M: Hans de Goede T: git git://anongit.freedesktop.org/drm/drm-misc diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig index f6e13e18c9ca..928bbf5cdc10 100644 --- a/drivers/gpu/drm/Kconfig +++ b/drivers/gpu/drm/Kconfig @@ -396,6 +396,8 @@ source "drivers/gpu/drm/aspeed/Kconfig" source "drivers/gpu/drm/mcde/Kconfig" +source "drivers/gpu/drm/gud/Kconfig" + # Keep legacy drivers last menuconfig DRM_LEGACY diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile index 0d17662dde0a..86af6c2da40d 100644 --- a/drivers/gpu/drm/Makefile +++ b/drivers/gpu/drm/Makefile @@ -123,3 +123,4 @@ obj-$(CONFIG_DRM_LIMA) += lima/ obj-$(CONFIG_DRM_PANFROST) += panfrost/ obj-$(CONFIG_DRM_ASPEED_GFX) += aspeed/ obj-$(CONFIG_DRM_MCDE) += mcde/ +obj-y += gud/ diff --git a/drivers/gpu/drm/gud/Kconfig b/drivers/gpu/drm/gud/Kconfig new file mode 100644 index ..203d4490f1c7 --- /dev/null +++ b/drivers/gpu/drm/gud/Kconfig @@ -0,0 +1,14 @@ +# SPDX-License-Identifier: GPL-2.0 + +config DRM_GUD + tristate "Generic USB Display" + depends on DRM && USB + select LZ4_COMPRESS + select DRM_KMS_HELPER + select DRM_GEM_SHMEM_HELPER + select DRM_BACKLIGHT_HELPER + help + This is a DRM display driver for Generic USB Displays or display + adapters. + + If M is selected the module will be called gud_drm. diff --git a/drivers/gpu/drm/gud/Makefile b/drivers/gpu/drm/gud/Makefile new file mode 100644 index ..73ed7ef3da94 --- /dev/null +++ b/drivers/gpu/drm/gud/Makefile @@ -0,0 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 + +gud_drm-objs := gud_drm_drv.o gud_drm_pipe.o gud_drm_connector.o +obj-$(CONFIG_DRM_GUD) += gud_drm.o diff --git a/drivers/gpu/drm/gud/gud_drm_connector.c b/drivers/gpu/drm/gud/gud_drm_connector.c new file mode 100644 index ..d1042b563a98 --- /dev/null +++ b/drivers/gpu/drm/gud/gud_drm_connector.c @@ -0,0 +1,629 @@ +// SPDX-License-Identifier: MIT +/* + * Copyright 2020 Noralf Trønnes + */ + +#include +#include +#include +#include +#include +#include +#include
[PATCH 03/10] drm/client: Add drm_client_init_from_id()
drm_client_init_from_id() provides a way for clients to add a client based on the minor. drm_client_register() is changed to return whether it was registered or not depending on the unplugged status of the DRM device. Its only caller drm_fbdev_generic_setup() runs inside probe() so it doesn't have to check. v2: - Move drm_client_modeset_set() to a separate patch with added functions. - Previous version had drm_client_init_from_id() call drm_client_register(). This put the client in a position where it could receive hotplugs during init in addition to akward error paths. Instead let drm_client_register() return status so clients can know if the DRM device is gone or not. Signed-off-by: Noralf Trønnes --- drivers/gpu/drm/drm_client.c | 48 +++- include/drm/drm_client.h | 4 ++- 2 files changed, 50 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/drm_client.c b/drivers/gpu/drm/drm_client.c index b031b45aa8ef..cb5ee9f1ffaa 100644 --- a/drivers/gpu/drm/drm_client.c +++ b/drivers/gpu/drm/drm_client.c @@ -112,6 +112,40 @@ int drm_client_init(struct drm_device *dev, struct drm_client_dev *client, } EXPORT_SYMBOL(drm_client_init); +/** + * drm_client_init_from_id - Initialise a DRM client + * @minor_id: DRM minor id + * @client: DRM client + * @name: Client name + * @funcs: DRM client functions (optional) + * + * This function looks up the drm_device using the minor id and initializes the client. + * + * See drm_client_init() and drm_client_register(). + * + * Returns: + * Zero on success or negative error code on failure. + */ +int drm_client_init_from_id(unsigned int minor_id, struct drm_client_dev *client, + const char *name, const struct drm_client_funcs *funcs) +{ + struct drm_minor *minor; + int ret; + + minor = drm_minor_acquire(minor_id); + if (IS_ERR(minor)) + return PTR_ERR(minor); + + mutex_lock(>dev->clientlist_mutex); + ret = drm_client_init(minor->dev, client, name, funcs); + mutex_unlock(>dev->clientlist_mutex); + + drm_minor_release(minor); + + return ret; +} +EXPORT_SYMBOL(drm_client_init_from_id); + /** * drm_client_register - Register client * @client: DRM client @@ -121,14 +155,26 @@ EXPORT_SYMBOL(drm_client_init); * drm_client_register() it is no longer permissible to call drm_client_release() * directly (outside the unregister callback), instead cleanup will happen * automatically on driver unload. + * + * Returns: + * True if the client has been registered, false if the DRM device has already + * been unregistered. */ -void drm_client_register(struct drm_client_dev *client) +bool drm_client_register(struct drm_client_dev *client) { struct drm_device *dev = client->dev; + int idx; + + if (!drm_dev_enter(client->dev, )) + return false; mutex_lock(>clientlist_mutex); list_add(>list, >clientlist); mutex_unlock(>clientlist_mutex); + + drm_dev_exit(idx); + + return true; } EXPORT_SYMBOL(drm_client_register); diff --git a/include/drm/drm_client.h b/include/drm/drm_client.h index 3ed5dee899fd..bbb5689fa9a8 100644 --- a/include/drm/drm_client.h +++ b/include/drm/drm_client.h @@ -109,8 +109,10 @@ struct drm_client_dev { int drm_client_init(struct drm_device *dev, struct drm_client_dev *client, const char *name, const struct drm_client_funcs *funcs); +int drm_client_init_from_id(unsigned int minor_id, struct drm_client_dev *client, + const char *name, const struct drm_client_funcs *funcs); void drm_client_release(struct drm_client_dev *client); -void drm_client_register(struct drm_client_dev *client); +bool drm_client_register(struct drm_client_dev *client); void drm_client_dev_unregister(struct drm_device *dev); void drm_client_dev_hotplug(struct drm_device *dev); -- 2.23.0 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH 01/10] backlight: Add backlight_device_get_by_name()
Add a way to lookup a backlight device based on its name. Will be used by a USB display gadget getting the name from configfs. Cc: Lee Jones Cc: Daniel Thompson Cc: Jingoo Han Signed-off-by: Noralf Trønnes --- drivers/video/backlight/backlight.c | 21 + include/linux/backlight.h | 1 + 2 files changed, 22 insertions(+) diff --git a/drivers/video/backlight/backlight.c b/drivers/video/backlight/backlight.c index cac3e35d7630..92d80aa0c0ef 100644 --- a/drivers/video/backlight/backlight.c +++ b/drivers/video/backlight/backlight.c @@ -432,6 +432,27 @@ struct backlight_device *backlight_device_get_by_type(enum backlight_type type) } EXPORT_SYMBOL(backlight_device_get_by_type); +/** + * backlight_device_get_by_name - Get backlight device by name + * @name: Device name + * + * This function looks up a backlight device by its name. It obtains a reference + * on the backlight device and it is the caller's responsibility to drop the + * reference by calling backlight_put(). + * + * Returns: + * A pointer to the backlight device if found, otherwise NULL. + */ +struct backlight_device *backlight_device_get_by_name(const char *name) +{ + struct device *dev; + + dev = class_find_device_by_name(backlight_class, name); + + return dev ? to_backlight_device(dev) : NULL; +} +EXPORT_SYMBOL(backlight_device_get_by_name); + /** * backlight_device_unregister - unregisters a backlight device object. * @bd: the backlight device object to be unregistered and freed. diff --git a/include/linux/backlight.h b/include/linux/backlight.h index c7d6b2e8c3b5..56e4580d4f55 100644 --- a/include/linux/backlight.h +++ b/include/linux/backlight.h @@ -190,6 +190,7 @@ extern void backlight_force_update(struct backlight_device *bd, extern int backlight_register_notifier(struct notifier_block *nb); extern int backlight_unregister_notifier(struct notifier_block *nb); extern struct backlight_device *backlight_device_get_by_type(enum backlight_type type); +struct backlight_device *backlight_device_get_by_name(const char *name); extern int backlight_device_set_brightness(struct backlight_device *bd, unsigned long brightness); #define to_backlight_device(obj) container_of(obj, struct backlight_device, dev) -- 2.23.0 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH 10/10] usb: gadget: function: Add Generic USB Display support
This adds the gadget side support for the Generic USB Display. It presents a DRM display device as a USB Display configured through configfs. The display is implemented as a vendor type USB interface with one bulk out endpoint. The protocol is implemented using control requests. lz4 compressed framebuffer data/pixels are sent over the bulk endpoint. The DRM part of the gadget is placed in the DRM subsystem since it reaches into the DRM internals. Cc: Felipe Balbi Signed-off-by: Noralf Trønnes --- .../ABI/testing/configfs-usb-gadget-gud_drm | 10 + MAINTAINERS | 2 + drivers/usb/gadget/Kconfig| 12 + drivers/usb/gadget/function/Makefile | 2 + drivers/usb/gadget/function/f_gud_drm.c | 678 ++ 5 files changed, 704 insertions(+) create mode 100644 Documentation/ABI/testing/configfs-usb-gadget-gud_drm create mode 100644 drivers/usb/gadget/function/f_gud_drm.c diff --git a/Documentation/ABI/testing/configfs-usb-gadget-gud_drm b/Documentation/ABI/testing/configfs-usb-gadget-gud_drm new file mode 100644 index ..d6d802c16eeb --- /dev/null +++ b/Documentation/ABI/testing/configfs-usb-gadget-gud_drm @@ -0,0 +1,10 @@ +What: /config/usb-gadget/gadget/functions/gud_drm.name +Date: Apr 2020 +KernelVersion: 5.8 +Description: + The attributes: + + drm_dev - DRM device number + backlight_dev - Backlight device name (optional) + The backlight brightness scale should be + perceptual not linear. diff --git a/MAINTAINERS b/MAINTAINERS index bb4609984e9a..fe56c68beb11 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -5287,7 +5287,9 @@ M:Noralf Trønnes S: Maintained W: https://github.com/notro/gud/wiki T: git git://anongit.freedesktop.org/drm/drm-misc +F: Documentation/ABI/testing/configfs-usb-gadget-gud_drm F: drivers/gpu/drm/gud/ +F: drivers/usb/gadget/function/f_gud_drm.c F: include/drm/gud_drm.h DRM DRIVER FOR GRAIN MEDIA GM12U320 PROJECTORS diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig index c6db0a0a340c..8d90add495b6 100644 --- a/drivers/usb/gadget/Kconfig +++ b/drivers/usb/gadget/Kconfig @@ -216,6 +216,9 @@ config USB_F_PRINTER config USB_F_TCM tristate +config USB_F_GUD_DRM + tristate + # this first set of drivers all depend on bulk-capable hardware. config USB_CONFIGFS @@ -483,6 +486,15 @@ config USB_CONFIGFS_F_TCM Both protocols can work on USB2.0 and USB3.0. UAS utilizes the USB 3.0 feature called streams support. +config USB_CONFIGFS_F_GUD_DRM + bool "Generic USB Display Gadget function" + depends on USB_CONFIGFS + depends on DRM + select DRM_GUD_GADGET + select USB_F_GUD_DRM + help + This presents a DRM display device as a Generic USB Display. + source "drivers/usb/gadget/legacy/Kconfig" endif # USB_GADGET diff --git a/drivers/usb/gadget/function/Makefile b/drivers/usb/gadget/function/Makefile index 5d3a6cf02218..cd71caa2a34c 100644 --- a/drivers/usb/gadget/function/Makefile +++ b/drivers/usb/gadget/function/Makefile @@ -50,3 +50,5 @@ usb_f_printer-y := f_printer.o obj-$(CONFIG_USB_F_PRINTER)+= usb_f_printer.o usb_f_tcm-y:= f_tcm.o obj-$(CONFIG_USB_F_TCM)+= usb_f_tcm.o +usb_f_gud_drm-y:= f_gud_drm.o +obj-$(CONFIG_USB_F_GUD_DRM)+= usb_f_gud_drm.o diff --git a/drivers/usb/gadget/function/f_gud_drm.c b/drivers/usb/gadget/function/f_gud_drm.c new file mode 100644 index ..9a2d6bb9739f --- /dev/null +++ b/drivers/usb/gadget/function/f_gud_drm.c @@ -0,0 +1,678 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2020 Noralf Trønnes + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +struct f_gud_drm { + struct usb_function func; + struct work_struct worker; + size_t max_buffer_size; + void *ctrl_req_buf; + + u8 interface_id; + struct usb_request *ctrl_req; + + struct usb_ep *bulk_ep; + struct usb_request *bulk_req; + + struct gud_drm_gadget *gdg; + + spinlock_t lock; /* Protects the following members: */ + bool ctrl_pending; + bool status_pending; + bool bulk_pending; + bool disable_pending; + u8 errno; + u16 request; + u16 value; +}; + +static inline struct f_gud_drm *func_to_f_gud_drm(struct usb_function *f) +{ + return container_of(f, struct f_gud_drm, func); +} + +struct f_gud_drm_opts { + struct usb_function_instance func_inst; + struct mutex lock; + int refcnt; + + unsigned int drm_dev; + const char *backlight_dev; +}; + +static inline struct f_gud_drm_opts *fi_to_f_gud_drm_opts(const struct
[PATCH 07/10] drm/format-helper: Add drm_fb_swab()
This replaces drm_fb_swab16() with drm_fb_swab() supporting 16 and 32-bit. Also make pixel line caching optional. Signed-off-by: Noralf Trønnes --- drivers/gpu/drm/drm_format_helper.c | 61 +++-- drivers/gpu/drm/drm_mipi_dbi.c | 2 +- include/drm/drm_format_helper.h | 4 +- 3 files changed, 44 insertions(+), 23 deletions(-) diff --git a/drivers/gpu/drm/drm_format_helper.c b/drivers/gpu/drm/drm_format_helper.c index 0897cb9aeaff..5c147c49668c 100644 --- a/drivers/gpu/drm/drm_format_helper.c +++ b/drivers/gpu/drm/drm_format_helper.c @@ -79,39 +79,60 @@ void drm_fb_memcpy_dstclip(void __iomem *dst, void *vaddr, EXPORT_SYMBOL(drm_fb_memcpy_dstclip); /** - * drm_fb_swab16 - Swap bytes into clip buffer - * @dst: RGB565 destination buffer - * @vaddr: RGB565 source buffer + * drm_fb_swab - Swap bytes into clip buffer + * @dst: Destination buffer + * @src: Source buffer * @fb: DRM framebuffer * @clip: Clip rectangle area to copy + * @cached: Source buffer is mapped cached (eg. not write-combined) + * + * If @cached is false a temporary buffer is used to cache one pixel line at a + * time to speed up slow uncached reads. + * + * This function does not apply clipping on dst, i.e. the destination + * is a small buffer containing the clip rect only. */ -void drm_fb_swab16(u16 *dst, void *vaddr, struct drm_framebuffer *fb, - struct drm_rect *clip) +void drm_fb_swab(void *dst, void *src, struct drm_framebuffer *fb, +struct drm_rect *clip, bool cached) { - size_t len = (clip->x2 - clip->x1) * sizeof(u16); + u8 cpp = fb->format->cpp[0]; + size_t len = drm_rect_width(clip) * cpp; + u16 *src16, *dst16 = dst; + u32 *src32, *dst32 = dst; unsigned int x, y; - u16 *src, *buf; + void *buf = NULL; - /* -* The cma memory is write-combined so reads are uncached. -* Speed up by fetching one line at a time. -*/ - buf = kmalloc(len, GFP_KERNEL); - if (!buf) + if (WARN_ON_ONCE(cpp == 1)) return; + if (!cached) + buf = kmalloc(len, GFP_KERNEL); + + src += clip_offset(clip, fb->pitches[0], cpp); + for (y = clip->y1; y < clip->y2; y++) { - src = vaddr + (y * fb->pitches[0]); - src += clip->x1; - memcpy(buf, src, len); - src = buf; - for (x = clip->x1; x < clip->x2; x++) - *dst++ = swab16(*src++); + if (buf) { + memcpy(buf, src, len); + src16 = buf; + src32 = buf; + } else { + src16 = src; + src32 = src; + } + + for (x = clip->x1; x < clip->x2; x++) { + if (cpp == 4) + *dst32++ = swab32(*src32++); + else + *dst16++ = swab16(*src16++); + } + + src += fb->pitches[0]; } kfree(buf); } -EXPORT_SYMBOL(drm_fb_swab16); +EXPORT_SYMBOL(drm_fb_swab); static void drm_fb_xrgb_to_rgb565_line(u16 *dbuf, u32 *sbuf, unsigned int pixels, diff --git a/drivers/gpu/drm/drm_mipi_dbi.c b/drivers/gpu/drm/drm_mipi_dbi.c index 16bff1be4b8a..bfefbcb69287 100644 --- a/drivers/gpu/drm/drm_mipi_dbi.c +++ b/drivers/gpu/drm/drm_mipi_dbi.c @@ -217,7 +217,7 @@ int mipi_dbi_buf_copy(void *dst, struct drm_framebuffer *fb, switch (fb->format->format) { case DRM_FORMAT_RGB565: if (swap) - drm_fb_swab16(dst, src, fb, clip); + drm_fb_swab(dst, src, fb, clip, !import_attach); else drm_fb_memcpy(dst, src, fb, clip); break; diff --git a/include/drm/drm_format_helper.h b/include/drm/drm_format_helper.h index ac220aa1a245..5f9e37032468 100644 --- a/include/drm/drm_format_helper.h +++ b/include/drm/drm_format_helper.h @@ -14,8 +14,8 @@ void drm_fb_memcpy(void *dst, void *vaddr, struct drm_framebuffer *fb, void drm_fb_memcpy_dstclip(void __iomem *dst, void *vaddr, struct drm_framebuffer *fb, struct drm_rect *clip); -void drm_fb_swab16(u16 *dst, void *vaddr, struct drm_framebuffer *fb, - struct drm_rect *clip); +void drm_fb_swab(void *dst, void *src, struct drm_framebuffer *fb, +struct drm_rect *clip, bool cached); void drm_fb_xrgb_to_rgb565(void *dst, void *vaddr, struct drm_framebuffer *fb, struct drm_rect *clip, bool swab); -- 2.23.0 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH 04/10] drm/client: Add drm_client_framebuffer_flush()
Some drivers need explicit flushing of buffer changes, add a function that does that. Signed-off-by: Noralf Trønnes --- drivers/gpu/drm/drm_client.c | 31 +++ include/drm/drm_client.h | 1 + 2 files changed, 32 insertions(+) diff --git a/drivers/gpu/drm/drm_client.c b/drivers/gpu/drm/drm_client.c index cb5ee9f1ffaa..8dbc2ecdcaea 100644 --- a/drivers/gpu/drm/drm_client.c +++ b/drivers/gpu/drm/drm_client.c @@ -483,6 +483,37 @@ void drm_client_framebuffer_delete(struct drm_client_buffer *buffer) } EXPORT_SYMBOL(drm_client_framebuffer_delete); +/** + * drm_client_framebuffer_flush - Manually flush client framebuffer + * @buffer: DRM client buffer (can be NULL) + * @rect: Damage rectangle (if NULL flushes all) + * + * This calls _framebuffer_funcs->dirty (if present) to flush buffer changes + * for drivers that need it. + * + * Returns: + * Zero on success or negative error code on failure. + */ +int drm_client_framebuffer_flush(struct drm_client_buffer *buffer, struct drm_rect *rect) +{ + struct drm_clip_rect clip_rect, *clip = NULL; + + if (!buffer || !buffer->fb || !buffer->fb->funcs->dirty) + return 0; + + if (rect) { + clip = _rect; + clip->x1 = rect->x1; + clip->y1 = rect->y1; + clip->x2 = rect->x2; + clip->y2 = rect->y2; + } + + return buffer->fb->funcs->dirty(buffer->fb, buffer->client->file, + 0, 0, clip, clip ? 1 : 0); +} +EXPORT_SYMBOL(drm_client_framebuffer_flush); + #ifdef CONFIG_DEBUG_FS static int drm_client_debugfs_internal_clients(struct seq_file *m, void *data) { diff --git a/include/drm/drm_client.h b/include/drm/drm_client.h index bbb5689fa9a8..6ef5364d6dfb 100644 --- a/include/drm/drm_client.h +++ b/include/drm/drm_client.h @@ -156,6 +156,7 @@ struct drm_client_buffer { struct drm_client_buffer * drm_client_framebuffer_create(struct drm_client_dev *client, u32 width, u32 height, u32 format); void drm_client_framebuffer_delete(struct drm_client_buffer *buffer); +int drm_client_framebuffer_flush(struct drm_client_buffer *buffer, struct drm_rect *rect); void *drm_client_buffer_vmap(struct drm_client_buffer *buffer); void drm_client_buffer_vunmap(struct drm_client_buffer *buffer); -- 2.23.0 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH 00/10] Generic USB Display driver
Hi, A while back I had the idea to turn a Raspberry Pi Zero into a $5 USB to HDMI/SDTV/DSI/DPI display adapter. This series adds a USB host driver and a device/gadget driver to achieve that. The reason for calling it 'Generic' is so anyone can make a USB display/adapter against this driver, all that's needed is to add a USB vid:pid. I was hoping to have someone working on a microcontroller based USB display by now, but unfortunately that has been delayed. It would have been nice to have a microcontroller implementation to ensure that I haven't made things unnecessary difficult to implement. Performance The one thing that decides how useful this all is, is how smooth an experience it gives. My hope was that it should not be noticeably laggy with ordinary office use on 1920x1080@RG16. I'm pleased to see that it's also possible to watch youtube movies, although not in fullscreen. Some of the main factors that affects performance: - Display resolution - Userspace providing damage reports (FB_DAMAGE_CLIPS or DRM_IOCTL_MODE_DIRTYFB) - Color depth (DRM_CAP_DUMB_PREFERRED_DEPTH = 16 if RGB565) - How well the frames compress (lz4) - Gadget device memory bandwidth, CPU power for decompression - (Big endian hosts will have to do byte swapping on the frames) I've tested these: - xorg-server on Pi4. This was nice and smooth since it uses DRM_IOCTL_MODE_DIRTYFB and honours DRM_CAP_DUMB_PREFERRED_DEPTH. - Ubuntu 20.04 GNOME on x86. This was useable, but not so good for movies. GNOME doesn't look at DRM_CAP_DUMB_PREFERRED_DEPTH and doesn't set FB_DAMAGE_CLIPS on the pageflips. I've made a short video to show what it looks like[1]. I have used a Pi4 as the gadget during development since it has much better memory bandwith (4000 vs 200 MBps)[2] and CPU than the PiZ. They both have the same gadget controller (dwc2). I did an RFC [3] of this 2 months ago where I looked at doing a Multi Function USB device. I gave up on that when I realised how much work the review process would be. So I stripped down to my original idea. I have made sure that the drivers will tolerate another USB interface of type VENDOR, so it's still possible for the display to be part of a multi function device. Noralf. [1] https://youtu.be/AhGZWwUm8JU [2] https://magpi.raspberrypi.org/articles/raspberry-pi-specs-benchmarks [3] https://patchwork.freedesktop.org/series/73508/ Noralf Trønnes (10): backlight: Add backlight_device_get_by_name() drm: Add backlight helper drm/client: Add drm_client_init_from_id() drm/client: Add drm_client_framebuffer_flush() drm/client: Add drm_client_modeset_check() drm/client: Add a way to set modeset, properties and rotation drm/format-helper: Add drm_fb_swab() drm: Add Generic USB Display driver drm/gud: Add functionality for the USB gadget side usb: gadget: function: Add Generic USB Display support .../ABI/testing/configfs-usb-gadget-gud_drm | 10 + Documentation/gpu/drm-kms-helpers.rst |6 + MAINTAINERS | 10 + drivers/gpu/drm/Kconfig |9 + drivers/gpu/drm/Makefile |2 + drivers/gpu/drm/drm_backlight_helper.c| 154 +++ drivers/gpu/drm/drm_client.c | 79 +- drivers/gpu/drm/drm_client_modeset.c | 174 ++- drivers/gpu/drm/drm_format_helper.c | 61 +- drivers/gpu/drm/drm_mipi_dbi.c|2 +- drivers/gpu/drm/gud/Kconfig | 20 + drivers/gpu/drm/gud/Makefile |5 + drivers/gpu/drm/gud/gud_drm_connector.c | 629 + drivers/gpu/drm/gud/gud_drm_drv.c | 624 + drivers/gpu/drm/gud/gud_drm_gadget.c | 1169 + drivers/gpu/drm/gud/gud_drm_internal.h| 66 + drivers/gpu/drm/gud/gud_drm_pipe.c| 423 ++ drivers/usb/gadget/Kconfig| 12 + drivers/usb/gadget/function/Makefile |2 + drivers/usb/gadget/function/f_gud_drm.c | 678 ++ drivers/video/backlight/backlight.c | 21 + include/drm/drm_backlight_helper.h|9 + include/drm/drm_client.h | 44 +- include/drm/drm_connector.h | 10 + include/drm/drm_format_helper.h |4 +- include/drm/gud_drm.h | 369 ++ include/linux/backlight.h |1 + 27 files changed, 4563 insertions(+), 30 deletions(-) create mode 100644 Documentation/ABI/testing/configfs-usb-gadget-gud_drm create mode 100644 drivers/gpu/drm/drm_backlight_helper.c create mode 100644 drivers/gpu/drm/gud/Kconfig create mode 100644 drivers/gpu/drm/gud/Makefile create mode 100644 drivers/gpu/drm/gud/gud_drm_connector.c create mode 100644 drivers/gpu/drm/gud/gud_drm_drv.c create mode 100644 drivers/gpu/drm/gud/gud_drm_gadget.c create mode 100644 drivers/gpu/drm/gud/gud_drm_internal.h create mode 100644
[PATCH 09/10] drm/gud: Add functionality for the USB gadget side
Since the USB gadget/device has to reach into the DRM internals, part of the code is placed in the DRM subsystem as a separate module. All calls into this module runs in process context and are serialized, except one function that runs in interrupt context. Since both the gadget side and the DRM side can disable the gadget, special care has been taken to make that safe. Signed-off-by: Noralf Trønnes --- drivers/gpu/drm/gud/Kconfig |6 + drivers/gpu/drm/gud/Makefile |1 + drivers/gpu/drm/gud/gud_drm_gadget.c | 1169 ++ include/drm/gud_drm.h| 13 + 4 files changed, 1189 insertions(+) create mode 100644 drivers/gpu/drm/gud/gud_drm_gadget.c diff --git a/drivers/gpu/drm/gud/Kconfig b/drivers/gpu/drm/gud/Kconfig index 203d4490f1c7..99bfbfbf9023 100644 --- a/drivers/gpu/drm/gud/Kconfig +++ b/drivers/gpu/drm/gud/Kconfig @@ -12,3 +12,9 @@ config DRM_GUD adapters. If M is selected the module will be called gud_drm. + +config DRM_GUD_GADGET + tristate + depends on DRM + select LZ4_DECOMPRESS + select BACKLIGHT_CLASS_DEVICE diff --git a/drivers/gpu/drm/gud/Makefile b/drivers/gpu/drm/gud/Makefile index 73ed7ef3da94..fb5cfbd93d0f 100644 --- a/drivers/gpu/drm/gud/Makefile +++ b/drivers/gpu/drm/gud/Makefile @@ -2,3 +2,4 @@ gud_drm-objs := gud_drm_drv.o gud_drm_pipe.o gud_drm_connector.o obj-$(CONFIG_DRM_GUD) += gud_drm.o +obj-$(CONFIG_DRM_GUD_GADGET) += gud_drm_gadget.o diff --git a/drivers/gpu/drm/gud/gud_drm_gadget.c b/drivers/gpu/drm/gud/gud_drm_gadget.c new file mode 100644 index ..a9c916abec85 --- /dev/null +++ b/drivers/gpu/drm/gud/gud_drm_gadget.c @@ -0,0 +1,1169 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright 2020 Noralf Trønnes + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "gud_drm_internal.h" + +/* + * Concurrency: + * Calls into this module from f_gud_drm are serialized and run in process + * context except gud_drm_gadget_ctrl_get() which is run in interrupt context. + * + * Termination: + * A DRM client can not release itself, only the DRM driver which resources the + * client uses can do that. + * This means that there are 2 paths to stop the gadget function: + * - Unregistering the DRM driver (module unload) + * - Disabling the USB gadget (configfs unbind) + * + * A use counter protects the gadget should the client go away. A kref is used + * to control the release of the gud_drm_gadget structure shared by the 2 actors. + * + * Backlight: + * If there's a backlight device it's attached to the first connector. + */ + +struct gud_drm_gadget_connector { + struct drm_connector *connector; + + const struct gud_drm_property *properties; + unsigned int num_properties; + const char *tv_mode_enum_names; + unsigned int num_tv_mode_enum_names; + struct backlight_device *backlight; + + spinlock_t lock; /* Protects the following members: */ + enum drm_connector_status status; + unsigned int width_mm; + unsigned int height_mm; + struct gud_drm_display_mode *modes; + unsigned int num_modes; + void *edid; + size_t edid_len; + bool changed; +}; + +struct gud_drm_gadget { + struct kref refcount; + refcount_t usecnt; + struct drm_client_dev client; + struct backlight_device *backlight; + + const u32 *formats; + unsigned int format_count; + + const struct gud_drm_property *properties; + unsigned int num_properties; + + struct gud_drm_gadget_connector *connectors; + unsigned int connector_count; + + struct drm_rect set_buffer_rect; + u32 set_buffer_length; + u8 set_buffer_compression; + u32 set_buffer_compressed_length; + + struct drm_client_buffer *buffer; + struct drm_client_buffer *buffer_check; + u8 brightness; + bool check_ok; + + size_t max_buffer_size; + void *work_buf; +}; + +static int gud_drm_gadget_probe_connector(struct gud_drm_gadget_connector *gconn) +{ + struct drm_connector *connector = gconn->connector; + struct gud_drm_display_mode *modes = NULL; + struct drm_device *drm = connector->dev; + struct drm_display_mode *mode; + void *edid_data, *edid = NULL; + unsigned int num_modes = 0; + size_t edid_len = 0; + unsigned long flags; + unsigned int i = 0; + int ret = 0; + + mutex_lock(>mode_config.mutex); + + connector->funcs->fill_modes(connector, +drm->mode_config.max_width, +drm->mode_config.max_height); + + list_for_each_entry(mode, >modes, head) + num_modes++; + + if (!num_modes) + goto update; + + modes =
[PATCH 05/10] drm/client: Add drm_client_modeset_check()
Add a way for client to check the configuration before comitting. Signed-off-by: Noralf Trønnes --- drivers/gpu/drm/drm_client_modeset.c | 35 include/drm/drm_client.h | 1 + 2 files changed, 32 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/drm_client_modeset.c b/drivers/gpu/drm/drm_client_modeset.c index 7443114bd713..177158ff2a40 100644 --- a/drivers/gpu/drm/drm_client_modeset.c +++ b/drivers/gpu/drm/drm_client_modeset.c @@ -966,7 +966,7 @@ bool drm_client_rotation(struct drm_mode_set *modeset, unsigned int *rotation) } EXPORT_SYMBOL(drm_client_rotation); -static int drm_client_modeset_commit_atomic(struct drm_client_dev *client, bool active) +static int drm_client_modeset_commit_atomic(struct drm_client_dev *client, bool active, bool check) { struct drm_device *dev = client->dev; struct drm_plane *plane; @@ -1033,7 +1033,10 @@ static int drm_client_modeset_commit_atomic(struct drm_client_dev *client, bool } } - ret = drm_atomic_commit(state); + if (check) + ret = drm_atomic_check_only(state); + else + ret = drm_atomic_commit(state); out_state: if (ret == -EDEADLK) @@ -1094,6 +1097,30 @@ static int drm_client_modeset_commit_legacy(struct drm_client_dev *client) return ret; } +/** + * drm_client_modeset_check() - Check CRTC configuration + * @client: DRM client + * + * Check modeset configuration. + * + * Returns: + * Zero on success or negative error code on failure. + */ +int drm_client_modeset_check(struct drm_client_dev *client) +{ + int ret; + + if (!drm_drv_uses_atomic_modeset(client->dev)) + return 0; + + mutex_lock(>modeset_mutex); + ret = drm_client_modeset_commit_atomic(client, true, true); + mutex_unlock(>modeset_mutex); + + return ret; +} +EXPORT_SYMBOL(drm_client_modeset_check); + /** * drm_client_modeset_commit_locked() - Force commit CRTC configuration * @client: DRM client @@ -1112,7 +1139,7 @@ int drm_client_modeset_commit_locked(struct drm_client_dev *client) mutex_lock(>modeset_mutex); if (drm_drv_uses_atomic_modeset(dev)) - ret = drm_client_modeset_commit_atomic(client, true); + ret = drm_client_modeset_commit_atomic(client, true, false); else ret = drm_client_modeset_commit_legacy(client); mutex_unlock(>modeset_mutex); @@ -1188,7 +1215,7 @@ int drm_client_modeset_dpms(struct drm_client_dev *client, int mode) mutex_lock(>modeset_mutex); if (drm_drv_uses_atomic_modeset(dev)) - ret = drm_client_modeset_commit_atomic(client, mode == DRM_MODE_DPMS_ON); + ret = drm_client_modeset_commit_atomic(client, mode == DRM_MODE_DPMS_ON, false); else drm_client_modeset_dpms_legacy(client, mode); mutex_unlock(>modeset_mutex); diff --git a/include/drm/drm_client.h b/include/drm/drm_client.h index 6ef5364d6dfb..b6ffa4863e45 100644 --- a/include/drm/drm_client.h +++ b/include/drm/drm_client.h @@ -164,6 +164,7 @@ int drm_client_modeset_create(struct drm_client_dev *client); void drm_client_modeset_free(struct drm_client_dev *client); int drm_client_modeset_probe(struct drm_client_dev *client, unsigned int width, unsigned int height); bool drm_client_rotation(struct drm_mode_set *modeset, unsigned int *rotation); +int drm_client_modeset_check(struct drm_client_dev *client); int drm_client_modeset_commit_locked(struct drm_client_dev *client); int drm_client_modeset_commit(struct drm_client_dev *client); int drm_client_modeset_dpms(struct drm_client_dev *client, int mode); -- 2.23.0 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH 02/10] drm: Add backlight helper
This adds a function that creates a backlight device for a connector. It does not deal with the KMS backlight ABI proposition[1] to add a connector property. It only takes the current best practise to standardise the creation of a backlight device for DRM drivers while we wait for the property. The brightness value is set using a connector state variable and an atomic commit. I have looked through some of the backlight users and this is what I've found: GNOME [2] - Brightness range: 0-100 Scale: Assumes perceptual Avoids setting the sysfs brightness value to zero if max_brightness >= 99. Can connect connector and backlight using the sysfs device. KDE [3] --- Brightness range: 0-100 Scale: Assumes perceptual Weston [4] -- Brightness range: 0-255 Scale: Assumes perceptual Chromium OS [5] --- Brightness range: 0-100 Scale: Depends on the sysfs file 'scale' which is a recent addition (2019) xserver [6] --- Brightness range: 0-x (driver specific) (1 is minimum, 0 is OFF) Scale: Assumes perceptual The builtin modesetting driver[7] does not support Backlight, Intel[8] does. [1] https://lore.kernel.org/dri-devel/4b17ba08-39f3-57dd-5aad-d37d844b0...@linux.intel.com/ [2] https://gitlab.gnome.org/GNOME/gnome-settings-daemon/-/blob/master/plugins/power/gsd-backlight.c [3] https://github.com/KDE/powerdevil/blob/master/daemon/backends/upower/backlighthelper.cpp [4] https://gitlab.freedesktop.org/wayland/weston/-/blob/master/libweston/backend-drm/drm.c [5] https://chromium.googlesource.com/chromiumos/platform2/+/refs/heads/master/power_manager/powerd/system/internal_backlight.cc [6] https://github.com/freedesktop/xorg-randrproto/blob/master/randrproto.txt [7] https://gitlab.freedesktop.org/xorg/xserver/-/blob/master/hw/xfree86/drivers/modesetting/drmmode_display.c [8] https://gitlab.freedesktop.org/xorg/driver/xf86-video-intel/-/blob/master/src/backlight.c Cc: Hans de Goede Cc: Jani Nikula Cc: Martin Peres Cc: Daniel Thompson Signed-off-by: Noralf Trønnes --- Documentation/gpu/drm-kms-helpers.rst | 6 + drivers/gpu/drm/Kconfig| 7 ++ drivers/gpu/drm/Makefile | 1 + drivers/gpu/drm/drm_backlight_helper.c | 154 + include/drm/drm_backlight_helper.h | 9 ++ include/drm/drm_connector.h| 10 ++ 6 files changed, 187 insertions(+) create mode 100644 drivers/gpu/drm/drm_backlight_helper.c create mode 100644 include/drm/drm_backlight_helper.h diff --git a/Documentation/gpu/drm-kms-helpers.rst b/Documentation/gpu/drm-kms-helpers.rst index 9668a7fe2408..29a2f4b49fd2 100644 --- a/Documentation/gpu/drm-kms-helpers.rst +++ b/Documentation/gpu/drm-kms-helpers.rst @@ -411,3 +411,9 @@ SHMEM GEM Helper Reference .. kernel-doc:: drivers/gpu/drm/drm_gem_shmem_helper.c :export: + +Backlight Helper Reference +== + +.. kernel-doc:: drivers/gpu/drm/drm_backlight_helper.c + :export: diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig index d0aa6cff2e02..f6e13e18c9ca 100644 --- a/drivers/gpu/drm/Kconfig +++ b/drivers/gpu/drm/Kconfig @@ -224,6 +224,13 @@ config DRM_GEM_SHMEM_HELPER help Choose this if you need the GEM shmem helper functions +config DRM_BACKLIGHT_HELPER + bool + depends on DRM + select BACKLIGHT_CLASS_DEVICE + help + Choose this if you need the backlight device helper functions + config DRM_VM bool depends on DRM && MMU diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile index 6493088a0fdd..0d17662dde0a 100644 --- a/drivers/gpu/drm/Makefile +++ b/drivers/gpu/drm/Makefile @@ -52,6 +52,7 @@ drm_kms_helper-$(CONFIG_DRM_FBDEV_EMULATION) += drm_fb_helper.o drm_kms_helper-$(CONFIG_DRM_KMS_CMA_HELPER) += drm_fb_cma_helper.o drm_kms_helper-$(CONFIG_DRM_DP_AUX_CHARDEV) += drm_dp_aux_dev.o drm_kms_helper-$(CONFIG_DRM_DP_CEC) += drm_dp_cec.o +drm_kms_helper-$(CONFIG_DRM_BACKLIGHT_HELPER) += drm_backlight_helper.o obj-$(CONFIG_DRM_KMS_HELPER) += drm_kms_helper.o obj-$(CONFIG_DRM_DEBUG_SELFTEST) += selftests/ diff --git a/drivers/gpu/drm/drm_backlight_helper.c b/drivers/gpu/drm/drm_backlight_helper.c new file mode 100644 index ..06e6a75d1d0a --- /dev/null +++ b/drivers/gpu/drm/drm_backlight_helper.c @@ -0,0 +1,154 @@ +// SPDX-License-Identifier: GPL-2.0 OR MIT +/* + * Copyright 2020 Noralf Trønnes + */ + +#include + +#include +#include +#include +#include + +static int drm_backlight_update_status(struct backlight_device *bd) +{ + struct drm_connector *connector = bl_get_data(bd); + struct drm_connector_state *connector_state; + struct drm_device *dev = connector->dev; + struct drm_modeset_acquire_ctx ctx; + struct drm_atomic_state *state; + int ret; + + state = drm_atomic_state_alloc(dev); + if (!state) + return -ENOMEM; + + drm_modeset_acquire_init(, 0); +
[PATCH 06/10] drm/client: Add a way to set modeset, properties and rotation
This adds functions for clients that need more control over the configuration than what's setup by drm_client_modeset_probe(). Connector, fb and display mode can be set using drm_client_modeset_set(). Plane rotation can be set using drm_client_modeset_set_rotation() and other properties using drm_client_modeset_set_property(). Property setting is only implemented for atomic drivers. Signed-off-by: Noralf Trønnes --- drivers/gpu/drm/drm_client_modeset.c | 139 +++ include/drm/drm_client.h | 38 +++- 2 files changed, 176 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/drm_client_modeset.c b/drivers/gpu/drm/drm_client_modeset.c index 177158ff2a40..1eef6869cae1 100644 --- a/drivers/gpu/drm/drm_client_modeset.c +++ b/drivers/gpu/drm/drm_client_modeset.c @@ -83,6 +83,10 @@ static void drm_client_modeset_release(struct drm_client_dev *client) } modeset->num_connectors = 0; } + + kfree(client->properties); + client->properties = NULL; + client->num_properties = 0; } void drm_client_modeset_free(struct drm_client_dev *client) @@ -879,6 +883,132 @@ int drm_client_modeset_probe(struct drm_client_dev *client, unsigned int width, } EXPORT_SYMBOL(drm_client_modeset_probe); +/** + * drm_client_modeset_set() - Set modeset configuration + * @client: DRM client + * @connector: Connector + * @mode: Display mode + * @fb: Framebuffer + * + * This function releases any current modeset info, including properties, and + * sets the new modeset in the client's modeset array. + * + * Returns: + * Zero on success or negative error code on failure. + */ +int drm_client_modeset_set(struct drm_client_dev *client, struct drm_connector *connector, + struct drm_display_mode *mode, struct drm_framebuffer *fb) +{ + struct drm_mode_set *modeset; + int ret = -ENOENT; + + mutex_lock(>modeset_mutex); + + drm_client_modeset_release(client); + + if (!connector || !mode || !fb) { + ret = 0; + goto unlock; + } + + drm_client_for_each_modeset(modeset, client) { + if (!connector_has_possible_crtc(connector, modeset->crtc)) + continue; + + modeset->mode = drm_mode_duplicate(client->dev, mode); + if (!modeset->mode) { + ret = -ENOMEM; + break; + } + + drm_mode_set_crtcinfo(modeset->mode, CRTC_INTERLACE_HALVE_V); + + drm_connector_get(connector); + modeset->connectors[modeset->num_connectors++] = connector; + + modeset->fb = fb; + ret = 0; + break; + } +unlock: + mutex_unlock(>modeset_mutex); + + return ret; +} +EXPORT_SYMBOL(drm_client_modeset_set); + +/** + * drm_client_modeset_set_property() - Set a property on the current configuration + * @client: DRM client + * @obj: DRM Mode Object + * @prop: DRM Property + * @value: Property value + * + * Note: Currently only implemented for atomic drivers. + * + * Returns: + * Zero on success or negative error code on failure. + */ +int drm_client_modeset_set_property(struct drm_client_dev *client, struct drm_mode_object *obj, + struct drm_property *prop, u64 value) +{ + struct drm_client_property *properties; + int ret = 0; + + if (!prop) + return -EINVAL; + + mutex_lock(>modeset_mutex); + + properties = krealloc(client->properties, + (client->num_properties + 1) * sizeof(*properties), GFP_KERNEL); + if (!properties) { + ret = -ENOMEM; + goto unlock; + } + + properties[client->num_properties].obj = obj; + properties[client->num_properties].prop = prop; + properties[client->num_properties].value = value; + client->properties = properties; + client->num_properties++; +unlock: + mutex_unlock(>modeset_mutex); + + return ret; +} +EXPORT_SYMBOL(drm_client_modeset_set_property); + +/** + * drm_client_modeset_set_rotation() - Set rotation on the current configuration + * @client: DRM client + * @value: Rotation value + * + * Returns: + * Zero on success or negative error code on failure. + */ +int drm_client_modeset_set_rotation(struct drm_client_dev *client, u64 value) +{ + struct drm_plane *plane = NULL; + struct drm_mode_set *modeset; + + mutex_lock(>modeset_mutex); + drm_client_for_each_modeset(modeset, client) { + if (modeset->mode) { + plane = modeset->crtc->primary; + break; + } + } + mutex_unlock(>modeset_mutex); + + if (!plane) + return -ENOENT; + + return drm_client_modeset_set_property(client, >base, +
[PATCH v3] backlight: lms283gf05: Convert to GPIO descriptors
This converts the lms283gf05 backlight driver to use GPIO descriptors and switches the single PXA Palm Z2 device over to defining these. Since the platform data was only used to convey GPIO information we can delete the platform data header. Notice that we define the proper active low semantics in the board file GPIO descriptor table (active low) and assert the reset line by bringing it to "1" (asserted). Cc: Marek Vasut Cc: Daniel Mack Cc: Haojian Zhuang Cc: Robert Jarzmik Signed-off-by: Linus Walleij --- ChangeLog v2->v3: - Fix a use-before-allocated bug discovered by compile tests. - Remove unused ret variable as autobuilders complained. ChangeLog v1->v2: - Bring up the GPIO de-asserted in probe() Marek: I saw this was written by you, are you regularly testing the Z2 device? --- arch/arm/mach-pxa/z2.c | 12 +--- drivers/video/backlight/lms283gf05.c | 42 +++- include/linux/spi/lms283gf05.h | 16 --- 3 files changed, 24 insertions(+), 46 deletions(-) delete mode 100644 include/linux/spi/lms283gf05.h diff --git a/arch/arm/mach-pxa/z2.c b/arch/arm/mach-pxa/z2.c index 21fd76bb09cd..89eb5243c85f 100644 --- a/arch/arm/mach-pxa/z2.c +++ b/arch/arm/mach-pxa/z2.c @@ -20,7 +20,6 @@ #include #include #include -#include #include #include #include @@ -578,8 +577,13 @@ static struct pxa2xx_spi_chip lms283_chip_info = { .gpio_cs= GPIO88_ZIPITZ2_LCD_CS, }; -static const struct lms283gf05_pdata lms283_pdata = { - .reset_gpio = GPIO19_ZIPITZ2_LCD_RESET, +static struct gpiod_lookup_table lms283_gpio_table = { + .dev_id = "spi2.0", /* SPI bus 2 chip select 0 */ + .table = { + GPIO_LOOKUP("gpio-pxa", GPIO19_ZIPITZ2_LCD_RESET, + "reset", GPIO_ACTIVE_LOW), + { }, + }, }; static struct spi_board_info spi_board_info[] __initdata = { @@ -595,7 +599,6 @@ static struct spi_board_info spi_board_info[] __initdata = { { .modalias = "lms283gf05", .controller_data= _chip_info, - .platform_data = _pdata, .max_speed_hz = 40, .bus_num= 2, .chip_select= 0, @@ -615,6 +618,7 @@ static void __init z2_spi_init(void) { pxa2xx_set_spi_info(1, _ssp1_master_info); pxa2xx_set_spi_info(2, _ssp2_master_info); + gpiod_add_lookup_table(_gpio_table); spi_register_board_info(spi_board_info, ARRAY_SIZE(spi_board_info)); } #else diff --git a/drivers/video/backlight/lms283gf05.c b/drivers/video/backlight/lms283gf05.c index 0e45685bcc1c..529c415eb03b 100644 --- a/drivers/video/backlight/lms283gf05.c +++ b/drivers/video/backlight/lms283gf05.c @@ -9,16 +9,16 @@ #include #include #include -#include +#include #include #include -#include #include struct lms283gf05_state { struct spi_device *spi; struct lcd_device *ld; + struct gpio_desc*reset; }; struct lms283gf05_seq { @@ -90,13 +90,13 @@ static const struct lms283gf05_seq disp_pdwnseq[] = { }; -static void lms283gf05_reset(unsigned long gpio, bool inverted) +static void lms283gf05_reset(struct gpio_desc *gpiod) { - gpio_set_value(gpio, !inverted); + gpiod_set_value(gpiod, 0); /* De-asserted */ mdelay(100); - gpio_set_value(gpio, inverted); + gpiod_set_value(gpiod, 1); /* Asserted */ mdelay(20); - gpio_set_value(gpio, !inverted); + gpiod_set_value(gpiod, 0); /* De-asserted */ mdelay(20); } @@ -125,18 +125,15 @@ static int lms283gf05_power_set(struct lcd_device *ld, int power) { struct lms283gf05_state *st = lcd_get_data(ld); struct spi_device *spi = st->spi; - struct lms283gf05_pdata *pdata = dev_get_platdata(>dev); if (power <= FB_BLANK_NORMAL) { - if (pdata) - lms283gf05_reset(pdata->reset_gpio, - pdata->reset_inverted); + if (st->reset) + lms283gf05_reset(st->reset); lms283gf05_toggle(spi, disp_initseq, ARRAY_SIZE(disp_initseq)); } else { lms283gf05_toggle(spi, disp_pdwnseq, ARRAY_SIZE(disp_pdwnseq)); - if (pdata) - gpio_set_value(pdata->reset_gpio, - pdata->reset_inverted); + if (st->reset) + gpiod_set_value(st->reset, 1); /* Asserted */ } return 0; @@ -150,24 +147,17 @@ static struct lcd_ops lms_ops = { static int lms283gf05_probe(struct spi_device *spi) { struct lms283gf05_state *st; - struct lms283gf05_pdata *pdata = dev_get_platdata(>dev); struct lcd_device *ld; - int ret = 0; - - if (pdata != NULL) { - ret = devm_gpio_request_one(>dev, pdata->reset_gpio, -
Re: [PATCH] backlight: lms283gf05: Convert to GPIO descriptors
Hi Linus, I love your patch! Perhaps something to improve: [auto build test WARNING on backlight/for-backlight-next] [also build test WARNING on arm-soc/for-next spi/for-next tegra-drm/drm/tegra/for-next v5.7-rc3 next-20200428] [if your patch is applied to the wrong git tree, please drop us a note to help improve the system. BTW, we also suggest to use '--base' option to specify the base tree in git format-patch, please see https://stackoverflow.com/a/37406982] url: https://github.com/0day-ci/linux/commits/Linus-Walleij/backlight-lms283gf05-Convert-to-GPIO-descriptors/20200429-181222 base: https://git.kernel.org/pub/scm/linux/kernel/git/lee/backlight.git for-backlight-next config: c6x-allyesconfig (attached as .config) compiler: c6x-elf-gcc (GCC) 9.3.0 reproduce: wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross chmod +x ~/bin/make.cross # save the attached .config to linux build tree COMPILER_INSTALL_PATH=$HOME/0day GCC_VERSION=9.3.0 make.cross ARCH=c6x If you fix the issue, kindly add following tag as appropriate Reported-by: kbuild test robot All warnings (new ones prefixed by >>): drivers/video/backlight/lms283gf05.c: In function 'lms283gf05_probe': drivers/video/backlight/lms283gf05.c:151:6: warning: unused variable 'ret' [-Wunused-variable] 151 | int ret = 0; | ^~~ >> drivers/video/backlight/lms283gf05.c:153:12: warning: 'st' is used >> uninitialized in this function [-Wuninitialized] 153 | st->reset = gpiod_get_optional(>dev, "reset", GPIOD_OUT_HIGH); | ~~^~~~ vim +/st +153 drivers/video/backlight/lms283gf05.c 146 147 static int lms283gf05_probe(struct spi_device *spi) 148 { 149 struct lms283gf05_state *st; 150 struct lcd_device *ld; > 151 int ret = 0; 152 > 153 st->reset = gpiod_get_optional(>dev, "reset", > GPIOD_OUT_HIGH); 154 if (st->reset) 155 gpiod_set_consumer_name(st->reset, "LMS283GF05 RESET"); 156 157 st = devm_kzalloc(>dev, sizeof(struct lms283gf05_state), 158 GFP_KERNEL); 159 if (st == NULL) 160 return -ENOMEM; 161 162 ld = devm_lcd_device_register(>dev, "lms283gf05", >dev, st, 163 _ops); 164 if (IS_ERR(ld)) 165 return PTR_ERR(ld); 166 167 st->spi = spi; 168 st->ld = ld; 169 170 spi_set_drvdata(spi, st); 171 172 /* kick in the LCD */ 173 if (st->reset) 174 lms283gf05_reset(st->reset); 175 lms283gf05_toggle(spi, disp_initseq, ARRAY_SIZE(disp_initseq)); 176 177 return 0; 178 } 179 --- 0-DAY CI Kernel Test Service, Intel Corporation https://lists.01.org/hyperkitty/list/kbuild-...@lists.01.org .config.gz Description: application/gzip ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel