1
0
mirror of https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git synced 2026-01-11 17:10:13 +00:00

Compare commits

...

97 Commits

Author SHA1 Message Date
Linus Torvalds
305230142a More power management updates for 6.7-rc1
- Add support for several Qualcomm SoC versions to the Qualcomm cpufreq
    driver (Robert Marko, Varadarajan Narayanan).
 
  - Fix a reference to a removed document in the cpupower utility
    documentation (Vegard Nossum).
 -----BEGIN PGP SIGNATURE-----
 
 iQJGBAABCAAwFiEE4fcc61cGeeHD/fCwgsRv/nhiVHEFAmVKlOESHHJqd0Byand5
 c29ja2kubmV0AAoJEILEb/54YlRx1kUP/RqJkLw/HzQ0AErnhlcQ/UO3sYkxdqEy
 OwoBHSmX8fYWkXgBsBLbZYklWPi7GKhuKqMnodt0DcXONoF/2ZpJ3ZkYD3E6KWvC
 BhbBx8+ciU9IeLPmVDd+rJpHMFKwGsf8sVNoZaCa2fTqMpcFAskI7i3w+dqfc6pe
 UYD7Cp1Tmm1fBQRXRqIY/z+aak9TgxG53RIQrHhP6qeJ9YZ+ixVofWtJofkynf7V
 5ZtSjphn5iHOXdHaAcjRTUjPJn65MFeJ0/ElqG7O42mRbFBwE2jt6m8Rnjh8T6xx
 uz/ogP11hKaK5E1c4csR5BQegzk6PdUZVNv/dauWKFjat/yyNSLIqena+lJKNVjW
 X+XEV6akO32AJ/uwczl8vfCx4JzQVbzd7qqKqzi5CDvVyKwkKP0t2resThFKwYFU
 CBnmK2aGa4vpEEEiqzgAkjCecML77pcuhGNSwhi9gZQ1GezVIuend5GbYXAYSrs/
 B0MHEvQYY1Omq3N4qNPOI6JhvULRRbniVr3l1Dbgf9khRIOA6lE+ONlzaZ0yxzBM
 gNqQjGzMN7e9kPe8BCXFRx2guoPIw53Z42mrDJneSD4wX3dunWcXtzO8eLP+O9/h
 y0efGLjcvFLX+nyLJ3Pj0RQ6J7tMfVhw2Df3o6m7t0AGic/0E+rSR+Y61+vZ3TGQ
 UGwZz0Zul5Mb
 =f4QJ
 -----END PGP SIGNATURE-----

Merge tag 'pm-6.7-rc1-2' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm

Pull more power management updates from Rafael Wysocki:
 "These add new hardware support to a cpufreq driver and fix cpupower
  utility documentation:

   - Add support for several Qualcomm SoC versions to the Qualcomm
     cpufreq driver (Robert Marko, Varadarajan Narayanan)

   - Fix a reference to a removed document in the cpupower utility
     documentation (Vegard Nossum)"

* tag 'pm-6.7-rc1-2' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm:
  cpufreq: qcom-nvmem: Introduce cpufreq for ipq95xx
  cpufreq: qcom-nvmem: Enable cpufreq for ipq53xx
  cpufreq: qcom-nvmem: add support for IPQ8074
  cpupower: fix reference to nonexistent document
2023-11-07 17:16:23 -08:00
Linus Torvalds
25b6377007 drm next and fixes for 6.7-rc1
renesas:
 - atomic conversion
 - DT support
 
 ssd13xx:
 - dt binding fix for ssd132x
 - Initialize ssd130x crtc_state to NULL.
 
 amdgpu:
 - Fix RAS support check
 - RAS fixes
 - MES fixes
 - SMU13 fixes
 - Contiguous memory allocation fix
 - BACO fixes
 - GPU reset fixes
 - Min power limit fixes
 - GFX11 fixes
 - USB4/TB hotplug fixes
 - ARM regression fix
 - GFX9.4.3 fixes
 - KASAN/KCSAN stack size check fixes
 - SR-IOV fixes
 - SMU14 fixes
 - PSP13 fixes
 - Display blend fixes
 - Flexible array size fixes
 
 amdkfd:
 - GPUVM fix
 
 radeon:
 - Flexible array size fixes
 -----BEGIN PGP SIGNATURE-----
 
 iQIzBAABCAAdFiEEEKbZHaGwW9KfbeusDHTzWXnEhr4FAmVJmdsACgkQDHTzWXnE
 hr5hphAAoFdk4ma7TauUNyP3JoUwht+Ohm9NcUHq/9P9kOCwPIIehxMZnwPoTGyw
 VWwXpqpeVsW6zyMgfxWq/+P1S1C5LvZ1HLccbP3xv327fUZ1QnLapHwFxT1SYNpi
 Tw5qhQN/cwNOX0Pc9uBavYmJzf54OhvPxt2CHHPDShsHBOBc0Gd88gKJr7GWUF5M
 Ri6i20Tfsgq8AopWQj9628TT+y/aN3rVIfYYBiNejxejlFtt1HODkKFX3DuBNPOI
 bZOtQm11cbxmX7/2RI92mI20axUb4UMNIQFDYEl3bVlyPyEhhwKPQMSDxhQQodPg
 8zMY9Fbl4Z4VaOFEDbpiRv/0/HeWoLefmpQ5LZbz35RhKLTkwsWXHUELPUEj3uTr
 7+EnLwuvQdtbT9W2J8btO7v1dHOy86ArlnmqNjB2cEnvGaR3DNM4jxPVLn60SyAc
 N7CFWNU4EoJf02XhwAludYa5pQHEaTFL8ss6TSoRWXuHHg1vNdu2SorOvkcGkg28
 q/t28gZDZaOpXfMmf3ec+PHhO6nxXLXJRbiksVP/rpXQQ42cEI72hr6//UYLRuzg
 BbYPZ8uXmDjsSZIqYceZwc3Vr6oEmD6EAzHM9+zwS5h0IZ12jKTmFiDEAhG2DwoG
 8PCaj5UXkxVK+6iHndz8Qwg4+Fu1j5nodKM+vBNem/iSnxC/OVw=
 =TsFN
 -----END PGP SIGNATURE-----

Merge tag 'drm-next-2023-11-07' of git://anongit.freedesktop.org/drm/drm

Pull more drm updates from Dave Airlie:
 "Geert pointed out I missed the renesas reworks in my main pull, so
  this pull contains the renesas next work for atomic conversion and DT
  support.

  It also contains a bunch of amdgpu and some small ssd13xx fixes.

  renesas:
   - atomic conversion
   - DT support

  ssd13xx:
   - dt binding fix for ssd132x
   - Initialize ssd130x crtc_state to NULL.

  amdgpu:
   - Fix RAS support check
   - RAS fixes
   - MES fixes
   - SMU13 fixes
   - Contiguous memory allocation fix
   - BACO fixes
   - GPU reset fixes
   - Min power limit fixes
   - GFX11 fixes
   - USB4/TB hotplug fixes
   - ARM regression fix
   - GFX9.4.3 fixes
   - KASAN/KCSAN stack size check fixes
   - SR-IOV fixes
   - SMU14 fixes
   - PSP13 fixes
   - Display blend fixes
   - Flexible array size fixes

  amdkfd:
   - GPUVM fix

  radeon:
   - Flexible array size fixes"

* tag 'drm-next-2023-11-07' of git://anongit.freedesktop.org/drm/drm: (83 commits)
  drm/amd/display: Enable fast update on blendTF change
  drm/amd/display: Fix blend LUT programming
  drm/amd/display: Program plane color setting correctly
  drm/amdgpu: Query and report boot status
  drm/amdgpu: Add psp v13 function to query boot status
  drm/amd/swsmu: remove fw version check in sw_init.
  drm/amd/swsmu: update smu v14_0_0 driver if and metrics table
  drm/amdgpu: Add C2PMSG_109/126 reg field shift/masks
  drm/amdgpu: Optimize the asic type fix code
  drm/amdgpu: fix GRBM read timeout when do mes_self_test
  drm/amdgpu: check recovery status of xgmi hive in ras_reset_error_count
  drm/amd/pm: only check sriov vf flag once when creating hwmon sysfs
  drm/amdgpu: Attach eviction fence on alloc
  drm/amdkfd: Improve amdgpu_vm_handle_moved
  drm/amd/display: Increase frame warning limit with KASAN or KCSAN in dml2
  drm/amd/display: Avoid NULL dereference of timing generator
  drm/amdkfd: Update cache info for GFX 9.4.3
  drm/amdkfd: Populate cache info for GFX 9.4.3
  drm/amdgpu: don't put MQDs in VRAM on ARM | ARM64
  drm/amdgpu/smu13: drop compute workload workaround
  ...
2023-11-07 17:10:02 -08:00
Rafael J. Wysocki
36cbb924d6 Merge branch 'pm-tools'
Merge cpupower utility update for 6.7-rc1:

 - Fix a reference to a removed document in the cpupower utility
   documentation (Vegard Nossum).

* pm-tools:
  cpupower: fix reference to nonexistent document
2023-11-07 20:46:13 +01:00
Rafael J. Wysocki
d53f7f7a74 Merge branch 'pm-cpufreq'
Merge branch 'pm-cpufreq'

Merge additional Qualcomm cpufreq driver updates for 6.7-rc1:

 - Add support for several Qualcomm SoC versions (Robert Marko,
   Varadarajan Narayanan).

* pm-cpufreq:
  cpufreq: qcom-nvmem: Introduce cpufreq for ipq95xx
  cpufreq: qcom-nvmem: Enable cpufreq for ipq53xx
  cpufreq: qcom-nvmem: add support for IPQ8074
2023-11-07 20:45:12 +01:00
Dave Airlie
9ccde17d46 amd-drm-next-6.7-2023-11-03:
amdgpu:
 - Fix RAS support check
 - RAS fixes
 - MES fixes
 - SMU13 fixes
 - Contiguous memory allocation fix
 - BACO fixes
 - GPU reset fixes
 - Min power limit fixes
 - GFX11 fixes
 - USB4/TB hotplug fixes
 - ARM regression fix
 - GFX9.4.3 fixes
 - KASAN/KCSAN stack size check fixes
 - SR-IOV fixes
 - SMU14 fixes
 - PSP13 fixes
 - Display blend fixes
 - Flexible array size fixes
 
 amdkfd:
 - GPUVM fix
 
 radeon:
 - Flexible array size fixes
 -----BEGIN PGP SIGNATURE-----
 
 iHUEABYKAB0WIQQgO5Idg2tXNTSZAr293/aFa7yZ2AUCZUUr4AAKCRC93/aFa7yZ
 2EycAQChYxkqbqfKqhJrU7lyz8EEBybis8UzshmHZnCCQF7ZGgD/a8UUhjr/7itI
 0n/hVEuu0sOVGaC8UQ0M8bl10NTvigI=
 =9rw/
 -----END PGP SIGNATURE-----

Merge tag 'amd-drm-next-6.7-2023-11-03' of https://gitlab.freedesktop.org/agd5f/linux into drm-next

amd-drm-next-6.7-2023-11-03:

amdgpu:
- Fix RAS support check
- RAS fixes
- MES fixes
- SMU13 fixes
- Contiguous memory allocation fix
- BACO fixes
- GPU reset fixes
- Min power limit fixes
- GFX11 fixes
- USB4/TB hotplug fixes
- ARM regression fix
- GFX9.4.3 fixes
- KASAN/KCSAN stack size check fixes
- SR-IOV fixes
- SMU14 fixes
- PSP13 fixes
- Display blend fixes
- Flexible array size fixes

amdkfd:
- GPUVM fix

radeon:
- Flexible array size fixes

Signed-off-by: Dave Airlie <airlied@redhat.com>

From: Alex Deucher <alexander.deucher@amd.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20231103173203.4912-1-alexander.deucher@amd.com
2023-11-06 11:25:14 +10:00
Dave Airlie
f056cb9681 Merge tag 'drm-misc-next-fixes-2023-11-02' of git://anongit.freedesktop.org/drm/drm-misc into drm-next
drm-misc-next-fixes for v6.7-rc1:

- dt binding fix for ssd132x
- Initialize ssd130x crtc_state to NULL.

Signed-off-by: Dave Airlie <airlied@redhat.com>
From: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/58f40043-bb8a-4716-bf07-89f6a9f56c4c@linux.intel.com
2023-11-06 11:24:30 +10:00
Ilya Bakoulin
6d5e0032a9 drm/amd/display: Enable fast update on blendTF change
[Why]
Full update is not required on surface blend TF change.

[How]
Update full_update_required condition.

Reviewed-by: Aric Cyr <aric.cyr@amd.com>
Acked-by: Hersen Wu <hersenxs.wu@amd.com>
Signed-off-by: Ilya Bakoulin <ilya.bakoulin@amd.com>
Tested-by: Daniel Wheeler <daniel.wheeler@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
2023-11-03 12:18:33 -04:00
Ilya Bakoulin
5d853ad5a8 drm/amd/display: Fix blend LUT programming
[Why]
LUT write index does not get reset to zero when writing the LUT values
for each separate RGB component, which results in wrong data for 2 of
the 3 components.

[How]
Reset LUT write index to zero before writing each component's data.

Reviewed-by: Krunoslav Kovac <krunoslav.kovac@amd.com>
Acked-by: Hersen Wu <hersenxs.wu@amd.com>
Signed-off-by: Ilya Bakoulin <ilya.bakoulin@amd.com>
Tested-by: Daniel Wheeler <daniel.wheeler@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
2023-11-03 12:18:33 -04:00
Sung Joon Kim
995dedb7a4 drm/amd/display: Program plane color setting correctly
[why]
There are some registers for plane
color that are skipped programming
on resume. Need to add those as part
of the sequence.

[how]
Add new function hook for programming
plane color control.

Reviewed-by: Duncan Ma <duncan.ma@amd.com>
Acked-by: Hersen Wu <hersenxs.wu@amd.com>
Signed-off-by: Sung Joon Kim <sungkim@amd.com>
Tested-by: Daniel Wheeler <daniel.wheeler@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
2023-11-03 12:18:33 -04:00
Hawking Zhang
23618280cc drm/amdgpu: Query and report boot status
Query boot status and report boot errors. A follow
up change is needed to stop GPU initialization if boot
fails.

v2: only invoke the call for dGPU (Le/Lijo)

Signed-off-by: Hawking Zhang <Hawking.Zhang@amd.com>
Reviewed-by: Tao Zhou <tao.zhou1@amd.com>
Reviewed-by: Yang Wang <kevinyang.wang@amd.com>
Reviewed-by: Le Ma <le.ma@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
2023-11-03 12:18:33 -04:00
Hawking Zhang
df57e019d5 drm/amdgpu: Add psp v13 function to query boot status
Add psp v13 function to query boot status.

v2: limit the use case to dGPU only (Lijo)

Signed-off-by: Hawking Zhang <Hawking.Zhang@amd.com>
Reviewed-by: Tao Zhou <tao.zhou1@amd.com>
Reviewed-by: Yang Wang <kevinyang.wang@amd.com>
Reviewed-by: Le Ma <le.ma@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
2023-11-03 12:18:33 -04:00
Li Ma
908cebc9a4 drm/amd/swsmu: remove fw version check in sw_init.
dorp fw version check and using max table size to init table.

Signed-off-by: Li Ma <li.ma@amd.com>
Reviewed-by: Yifan Zhang <yifan1.zhang@amd.com>
Reviewed-by: Yang Wang <kevinyang.wang@amd.com>
Acked-by: Alex Deucher <alexander.deucher@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
2023-11-03 12:18:33 -04:00
Li Ma
34ec3cedca drm/amd/swsmu: update smu v14_0_0 driver if and metrics table
Update driver if headers and metrics table in smu v14_0_0 after smu fw promotion.
Drop the legacy metrics table and add warning of checking pmfw version.

Signed-off-by: Li Ma <li.ma@amd.com>
Reviewed-by: Yifan Zhang <yifan1.zhang@amd.com>
Acked-by: Alex Deucher <alexander.deucher@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
2023-11-03 12:18:33 -04:00
Hawking Zhang
38a64e3a33 drm/amdgpu: Add C2PMSG_109/126 reg field shift/masks
Add MP0_C2PMSG_109/126 register field shift/masks
that are used to identify boot status by driver.

Signed-off-by: Hawking Zhang <Hawking.Zhang@amd.com>
Reviewed-by: Tao Zhou <tao.zhou1@amd.com>
Reviewed-by: Yang Wang <kevinyang.wang@amd.com>
Reviewed-by: Le Ma <le.ma@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
2023-11-03 12:18:33 -04:00
Ma Jun
dbab63561b drm/amdgpu: Optimize the asic type fix code
Use a new struct array to define the asic information which
asic type needs to be fixed.

Signed-off-by: Ma Jun <Jun.Ma2@amd.com>
Reviewed-by: Kenneth Feng <kenneth.feng@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
2023-11-03 12:18:32 -04:00
Tim Huang
36e7ff5c13 drm/amdgpu: fix GRBM read timeout when do mes_self_test
Use a proper MEID to make sure the CP_HQD_* and CP_GFX_HQD_* registers
can be touched when initialize the compute and gfx mqd in mes_self_test.
Otherwise, we expect no response from CP and an GRBM eventual timeout.

Signed-off-by: Tim Huang <Tim.Huang@amd.com>
Acked-by: Alex Deucher <alexander.deucher@amd.com>
Reviewed-by: Yifan Zhang <yifan1.zhang@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Cc: stable@vger.kernel.org
2023-11-03 12:18:32 -04:00
Tao Zhou
18eae367cb drm/amdgpu: check recovery status of xgmi hive in ras_reset_error_count
Handle xgmi hive case.

Suggested-by: Hawking Zhang <Hawking.Zhang@amd.com>
Signed-off-by: Tao Zhou <tao.zhou1@amd.com>
Reviewed-by: Stanley.Yang <Stanley.Yang@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
2023-11-03 12:18:32 -04:00
Ma Jun
88e5c8f874 drm/amd/pm: only check sriov vf flag once when creating hwmon sysfs
The current code checks sriov vf flag multiple times when creating
hwmon sysfs. So fix it.

Signed-off-by: Ma Jun <Jun.Ma2@amd.com>
Reviewed-by: Yang Wang <kevinyang.wang@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
2023-11-03 12:18:32 -04:00
Felix Kuehling
0e2e7c5b3d drm/amdgpu: Attach eviction fence on alloc
Instead of attaching the eviction fence when a KFD BO is first mapped,
attach it when it is allocated or imported. This in preparation to allow
KFD BOs to be mapped using the render node API.

Signed-off-by: Felix Kuehling <Felix.Kuehling@amd.com>
Acked-by: Christian König <christian.koenig@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
2023-11-03 12:18:32 -04:00
Felix Kuehling
5a104cb97c drm/amdkfd: Improve amdgpu_vm_handle_moved
Let amdgpu_vm_handle_moved update all BO VA mappings of BOs reserved by
the caller. This will be useful for handling extra BO VA mappings in
KFD VMs that are managed through the render node API.

v2: rebase against drm_exec changes (Alex)

Signed-off-by: Felix Kuehling <Felix.Kuehling@amd.com>
Reviewed-by: Christian König <christian.koenig@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
2023-11-03 12:18:32 -04:00
Nathan Chancellor
6740ec97bc drm/amd/display: Increase frame warning limit with KASAN or KCSAN in dml2
When building ARCH=x86_64 allmodconfig with clang, which will typically
have sanitizers enabled, there is a warning about a large stack frame.

  drivers/gpu/drm/amd/amdgpu/../display/dc/dml2/display_mode_core.c:6265:13: error: stack frame size (2520) exceeds limit (2048) in 'dml_prefetch_check' [-Werror,-Wframe-larger-than]
   6265 | static void dml_prefetch_check(struct display_mode_lib_st *mode_lib)
        |             ^
  1 error generated.

Notably, GCC 13.2.0 does not do too much of a better job, as it is right
at the current limit of 2048 (and others have reported being over with
older GCC versions):

  drivers/gpu/drm/amd/amdgpu/../display/dc/dml2/display_mode_core.c: In function 'dml_prefetch_check':
  drivers/gpu/drm/amd/amdgpu/../display/dc/dml2/display_mode_core.c:6705:1: error: the frame size of 2048 bytes is larger than 1800 bytes [-Werror=frame-larger-than=]
   6705 | }
        | ^

In the past, these warnings have been avoided by reducing the number of
parameters to various functions so that not as many arguments need to be
passed on the stack. However, these patches take a good amount of effort
to write despite being mechanical due to code structure and complexity
and they are never carried forward to new generations of the code so
that effort has to be expended every new hardware generation, which
becomes harder to justify as time goes on.

To avoid having a noticeable or lengthy breakage in all{mod,yes}config,
which are easy testing targets that have -Werror enabled, increase the
limit for configurations that have KASAN or KCSAN enabled by 50% so that
cases of extremely poor code generation can still be caught while not
breaking the majority of builds. CONFIG_KMSAN also causes high stack
usage but the frame limit is already set to zero when it is enabled,
which is accounted for by the check for CONFIG_FRAME_WARN=0 in the dml2
Makefile.

Signed-off-by: Nathan Chancellor <nathan@kernel.org>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
2023-11-03 11:59:52 -04:00
Wayne Lin
b1904ed480 drm/amd/display: Avoid NULL dereference of timing generator
[Why & How]
Check whether assigned timing generator is NULL or not before
accessing its funcs to prevent NULL dereference.

Reviewed-by: Jun Lei <jun.lei@amd.com>
Acked-by: Hersen Wu <hersenxs.wu@amd.com>
Signed-off-by: Wayne Lin <wayne.lin@amd.com>
Tested-by: Daniel Wheeler <daniel.wheeler@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
2023-11-03 11:59:51 -04:00
Mukul Joshi
be457b2252 drm/amdkfd: Update cache info for GFX 9.4.3
Update cache info reporting based on compute and
memory partitioning modes.

Signed-off-by: Mukul Joshi <mukul.joshi@amd.com>
Reviewed-by: Felix Kuehling <Felix.Kuehling@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
2023-11-03 11:59:51 -04:00
Mukul Joshi
0ce8edae8b drm/amdkfd: Populate cache info for GFX 9.4.3
GFX 9.4.3 uses a new version of the GC info table which
contains the cache info. This patch adds a new function
to populate the cache info from IP discovery for GFX 9.4.3.

Signed-off-by: Mukul Joshi <mukul.joshi@amd.com>
Reviewed-by: Felix Kuehling <Felix.Kuehling@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
2023-11-03 11:59:51 -04:00
Alex Deucher
ba0fb4b48c drm/amdgpu: don't put MQDs in VRAM on ARM | ARM64
Issues were reported with commit 1cfb4d612127
("drm/amdgpu: put MQDs in VRAM") on an ADLINK Ampere
Altra Developer Platform (AVA developer platform).

Various ARM systems seem to have problems related
to PCIe and MMIO access.  In this case, I'm not sure
if this is specific to the ADLINK platform or ARM
in general.  Seems to be some coherency issue with
VRAM.  For now, just don't put MQDs in VRAM on ARM.

Link: https://lists.freedesktop.org/archives/amd-gfx/2023-October/100453.html
Fixes: 1cfb4d612127 ("drm/amdgpu: put MQDs in VRAM")
Acked-by: Christian König <christian.koenig@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Cc: alexey.klimov@linaro.org
2023-11-03 11:59:51 -04:00
Alex Deucher
23170863ea drm/amdgpu/smu13: drop compute workload workaround
This was fixed in PMFW before launch and is no longer
required.

Reviewed-by: Yang Wang <kevinyang.wang@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Cc: stable@vger.kernel.org # 6.1.x
2023-11-03 11:59:51 -04:00
Alex Deucher
3938eb956e drm/amdgpu: add a retry for IP discovery init
AMD dGPUs have integrated FW that runs as soon as the
device gets power and initializes the board (determines
the amount of memory, provides configuration details to
the driver, etc.).  For direct PCIe attached cards this
happens as soon as power is applied and normally completes
well before the OS has even started loading.  However, with
hotpluggable ports like USB4, the driver needs to wait for
this to complete before initializing the device.

This normally takes 60-100ms, but could take longer on
some older boards periodically due to memory training.

Retry for up to a second.  In the non-hotplug case, there
should be no change in behavior and this should complete
on the first try.

v2: adjust test criteria
v3: adjust checks for the masks, only enable on removable devices
v4: skip bif_fb_en check

Link: https://gitlab.freedesktop.org/drm/amd/-/issues/2925
Reviewed-by: Mario Limonciello <mario.limonciello@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Cc: stable@vger.kernel.org
2023-11-03 11:59:51 -04:00
Perry Yuan
886b92f635 drm/amdgpu: ungate power gating when system suspend
[Why] During suspend, if GFX DPM is enabled and GFXOFF feature is
enabled the system may get hung. So, it is suggested to disable
GFXOFF feature during suspend and enable it after resume.

[How] Update the code to disable GFXOFF feature during suspend and enable
it after resume.

[  311.396526] amdgpu 0000:03:00.0: amdgpu: SMU: I'm not done with your previous command: SMN_C2PMSG_66:0x0000001E SMN_C2PMSG_82:0x00000000
[  311.396530] amdgpu 0000:03:00.0: amdgpu: Fail to disable dpm features!
[  311.396531] [drm:amdgpu_device_ip_suspend_phase2 [amdgpu]] *ERROR* suspend of IP block <smu> failed -62

Acked-by: Yang Wang <kevinyang.wang@amd.com>
Reviewed-by: Kenneth Feng <kenneth.feng@amd.com>
Signed-off-by: Perry Yuan <perry.yuan@amd.com>
Signed-off-by: Kun Liu <kun.liu2@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Cc: stable@vger.kernel.org
2023-11-03 11:59:51 -04:00
José Pekkarinen
3a50f41bc2 drm/radeon: replace 1-element arrays with flexible-array members
Reported by coccinelle, the following patch will move the
following 1 element arrays to flexible arrays.

drivers/gpu/drm/radeon/atombios.h:5523:32-48: WARNING use flexible-array member instead (https://www.kernel.org/doc/html/latest/process/deprecated.html#zero-length-and-one-element-arrays)
drivers/gpu/drm/radeon/atombios.h:5545:32-48: WARNING use flexible-array member instead (https://www.kernel.org/doc/html/latest/process/deprecated.html#zero-length-and-one-element-arrays)
drivers/gpu/drm/radeon/atombios.h:5461:34-44: WARNING use flexible-array member instead (https://www.kernel.org/doc/html/latest/process/deprecated.html#zero-length-and-one-element-arrays)
drivers/gpu/drm/radeon/atombios.h:4447:30-40: WARNING use flexible-array member instead (https://www.kernel.org/doc/html/latest/process/deprecated.html#zero-length-and-one-element-arrays)
drivers/gpu/drm/radeon/atombios.h:4236:30-41: WARNING use flexible-array member instead (https://www.kernel.org/doc/html/latest/process/deprecated.html#zero-length-and-one-element-arrays)
drivers/gpu/drm/radeon/atombios.h:7095:28-45: WARNING use flexible-array member instead (https://www.kernel.org/doc/html/latest/process/deprecated.html#zero-length-and-one-element-arrays)
drivers/gpu/drm/radeon/atombios.h:3896:27-37: WARNING use flexible-array member instead (https://www.kernel.org/doc/html/latest/process/deprecated.html#zero-length-and-one-element-arrays)
drivers/gpu/drm/radeon/atombios.h:5443:16-25: WARNING use flexible-array member instead (https://www.kernel.org/doc/html/latest/process/deprecated.html#zero-length-and-one-element-arrays)
drivers/gpu/drm/radeon/atombios.h:5454:34-43: WARNING use flexible-array member instead (https://www.kernel.org/doc/html/latest/process/deprecated.html#zero-length-and-one-element-arrays)
drivers/gpu/drm/radeon/atombios.h:4603:21-32: WARNING use flexible-array member instead (https://www.kernel.org/doc/html/latest/process/deprecated.html#zero-length-and-one-element-arrays)
drivers/gpu/drm/radeon/atombios.h:4628:32-46: WARNING use flexible-array member instead (https://www.kernel.org/doc/html/latest/process/deprecated.html#zero-length-and-one-element-arrays)
drivers/gpu/drm/radeon/atombios.h:6285:29-39: WARNING use flexible-array member instead (https://www.kernel.org/doc/html/latest/process/deprecated.html#zero-length-and-one-element-arrays)
drivers/gpu/drm/radeon/atombios.h:4296:30-36: WARNING use flexible-array member instead (https://www.kernel.org/doc/html/latest/process/deprecated.html#zero-length-and-one-element-arrays)
drivers/gpu/drm/radeon/atombios.h:4756:28-36: WARNING use flexible-array member instead (https://www.kernel.org/doc/html/latest/process/deprecated.html#zero-length-and-one-element-arrays)
drivers/gpu/drm/radeon/atombios.h:4064:22-35: WARNING use flexible-array member instead (https://www.kernel.org/doc/html/latest/process/deprecated.html#zero-length-and-one-element-arrays)
drivers/gpu/drm/radeon/atombios.h:7327:9-24: WARNING use flexible-array member instead (https://www.kernel.org/doc/html/latest/process/deprecated.html#zero-length-and-one-element-arrays)
drivers/gpu/drm/radeon/atombios.h:7332:32-53: WARNING use flexible-array member instead (https://www.kernel.org/doc/html/latest/process/deprecated.html#zero-length-and-one-element-arrays)
drivers/gpu/drm/radeon/atombios.h:7362:26-41: WARNING use flexible-array member instead (https://www.kernel.org/doc/html/latest/process/deprecated.html#zero-length-and-one-element-arrays)
drivers/gpu/drm/radeon/atombios.h:7369:29-44: WARNING use flexible-array member instead (https://www.kernel.org/doc/html/latest/process/deprecated.html#zero-length-and-one-element-arrays)
drivers/gpu/drm/radeon/atombios.h:7349:24-32: WARNING use flexible-array member instead (https://www.kernel.org/doc/html/latest/process/deprecated.html#zero-length-and-one-element-arrays)
drivers/gpu/drm/radeon/atombios.h:7355:27-35: WARNING use flexible-array member instead (https://www.kernel.org/doc/html/latest/process/deprecated.html#zero-length-and-one-element-arrays)

Signed-off-by: José Pekkarinen <jose.pekkarinen@foxhound.fi>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
2023-11-03 11:59:51 -04:00
Alex Deucher
49afe91370 drm/amd: Fix UBSAN array-index-out-of-bounds for Powerplay headers
For pptable structs that use flexible array sizes, use flexible arrays.

Link: https://bugs.launchpad.net/ubuntu/+source/linux/+bug/2039926
Reviewed-by: Mario Limonciello <mario.limonciello@amd.com>
Acked-by: Christian König <christian.koenig@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
2023-11-03 11:59:51 -04:00
Alex Deucher
7b1c6263ea drm/amdgpu: don't use pci_is_thunderbolt_attached()
It's only valid on Intel systems with the Intel VSEC.
Use dev_is_removable() instead.  This should do the right
thing regardless of the platform.

Link: https://gitlab.freedesktop.org/drm/amd/-/issues/2925
Reviewed-by: Mario Limonciello <mario.limonciello@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Cc: stable@vger.kernel.org
2023-11-03 11:59:44 -04:00
Alex Deucher
432e664e7c drm/amdgpu: don't use ATRM for external devices
The ATRM ACPI method is for fetching the dGPU vbios rom
image on laptops and all-in-one systems.  It should not be
used for external add in cards.  If the dGPU is thunderbolt
connected, don't try ATRM.

v2: pci_is_thunderbolt_attached only works for Intel.  Use
    pdev->external_facing instead.
v3: dev_is_removable() seems to be what we want

Link: https://gitlab.freedesktop.org/drm/amd/-/issues/2925
Reviewed-by: Mario Limonciello <mario.limonciello@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Cc: stable@vger.kernel.org
2023-11-03 11:59:13 -04:00
Alex Deucher
b3c942bb6c drm/amdgpu/gfx10,11: use memcpy_to/fromio for MQDs
Since they were moved to VRAM, we need to use the IO
variants of memcpy.

Fixes: 1cfb4d612127 ("drm/amdgpu: put MQDs in VRAM")
Reviewed-by: Christian König <christian.koenig@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
2023-11-03 11:38:19 -04:00
Tao Zhou
f7aeee7346 drm/amdgpu: use mode-2 reset for RAS poison consumption
Switch from mode-1 reset to mode-2 for poison consumption.

Signed-off-by: Tao Zhou <tao.zhou1@amd.com>
Reviewed-by: Stanley.Yang <Stanley.Yang@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
2023-11-03 11:38:13 -04:00
Lin.Cao
b77cc85bdb drm/amdgpu doorbell range should be set when gpu recovery
GFX doorbell range should be set after flr otherwise the gfx doorbell
range will be overlap with MEC.

v2: remove "amdgpu_sriov_vf" and "amdgpu_in_reset" check, and add grbm
select for the case of 2 gfx rings.

Signed-off-by: Lin.Cao <lincao12@amd.com>
Acked-by: ZhenGuo Yin <zhenguo.yin@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
2023-11-03 11:38:04 -04:00
Ma Jun
42ef313754 drm/amd/pm: Return 0 as default min power limit for legacy asics
Return 0 as the default min power limit for the asics use
powerplay.

Signed-off-by: Ma Jun <Jun.Ma2@amd.com>
Reviewed-by: Kenneth Feng <kenneth.feng@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
2023-11-03 11:37:38 -04:00
Rafael J. Wysocki
d1f6be54ea ARM cpufreq updates for 6.7
- Add support for several Qualcomm SoC versions (Robert Marko and
   Varadarajan Narayanan).
 -----BEGIN PGP SIGNATURE-----
 
 iQIzBAABCgAdFiEEx73Crsp7f6M6scA70rkcPK6BEhwFAmVDNtYACgkQ0rkcPK6B
 Ehwhuw//UKjJ+nRaAZsotW1in3bU8vRS4L/iLdLndxBTRhkB2Boki80ICYIxGaXB
 HU6+Trkw2SL+iWxYY2c/+xdNe5ZiNPZ/GIguPpPz6O+Pgv/krj25crdgAioiAxWc
 m0do2cMo0iyRGCEJvcrO+3EYDwN7RtwkEPfMT4B1OuJLgNXQQIBREuvJmslqsoqa
 dA4eNcg9d4bQt2wW0C2Zv3mh9/RMCVnA0s6dRN0WQg07Cdz5lr6J423y64VBrcIV
 nXhOwbj4gqDHsOIUJuezBW76CP5leDQ53hls/4a0Ct4Y5RCuC0VWJScrOE0B7ib4
 AHsaS0wz6Viu6FNpKLLT9sbi8zGcaYe35pgfkuyU1vUVX98a0vmtYK5KVRL6+sNO
 eUG3D3FTTyU4iBE9xecdW+Sy9xyUUdbVJBNVUoqK1Od3pw0VJ5sZngQvbD0YmcHS
 l5ggi076R+S1yuc7H54qQChXo6eSngju61dnvW2qVg+YOiYPkpezQZbM526R50vI
 z7Lx7VgyMgPCpJazl8foc6E+Mmgegcb6wJd0nEq11/KyQCTov5ky2pBcJMkeuctY
 lyp2qB/AtS14snZs7Im6EYWR+UdGJThjRAUHhxgwssxYGuKnQfccc3bVqw+feeHg
 rjyJ3LUuvXoIwbTWacff51u/+Wsa/ghx+byeNvyx0lobkoKA+Us=
 =yM+b
 -----END PGP SIGNATURE-----

Merge tag 'cpufreq-arm-updates-6.7-part2' of git://git.kernel.org/pub/scm/linux/kernel/git/vireshk/pm

Merge ARM cpufreq updates for 6.7 (part 2) from Viresh kumar:

"- Add support for several Qualcomm SoC versions (Robert Marko and
   Varadarajan Narayanan)."

* tag 'cpufreq-arm-updates-6.7-part2' of git://git.kernel.org/pub/scm/linux/kernel/git/vireshk/pm:
  cpufreq: qcom-nvmem: Introduce cpufreq for ipq95xx
  cpufreq: qcom-nvmem: Enable cpufreq for ipq53xx
  cpufreq: qcom-nvmem: add support for IPQ8074
  soc: qcom: socinfo: Add IDs for IPQ8174 family
  dt-bindings: arm: qcom,ids: Add IDs for IPQ8174 family
  dt-bindings: qcom: geni-se: Allow dma-coherent
  soc: qcom: socinfo: Add SoC ID for QCM6490
  dt-bindings: arm: qcom,ids: Add SoC ID for QCM6490
  soc: qcom: socinfo: Add SM8550-adjacent PMICs
  soc: qcom: wcnss_ctrl: Remove redundant initialization owner in wcnss_ctrl_driver
  soc: qcom: socinfo: Add Soc ID for SM7150P
  dt-bindings: arm: qcom,ids: Add Soc ID for SM7150P
  firmware: Add support for Qualcomm UEFI Secure Application
  firmware: qcom_scm: Add support for Qualcomm Secure Execution Environment SCM interface
  lib/ucs2_string: Add UCS-2 strscpy function
2023-11-03 15:31:57 +01:00
Rafael J. Wysocki
a563c99f22 linux-cpupower-6.7-rc1
This cpupower update for Linux 6.7-rc1 consists of a single fix to
 documentation to fix reference to a removed document.
 -----BEGIN PGP SIGNATURE-----
 
 iQIzBAABCgAdFiEEPZKym/RZuOCGeA/kCwJExA0NQxwFAmVBZZcACgkQCwJExA0N
 QxxB9w/+KfLlAOCThW9LZauqVsVJHzzMuDi6ctuvnUsy39Xf/VH22SzakhYoujfT
 vuQ43cLqIT/p9HkjbQnC0uJTx3nIIs/qWRWyklMn9ETAp+TP14ewTFRYAiPL/XRh
 GylTbCzh2QmU0oiR81Cq4bMRGkzywGHKi7g+E5LQ7ACz1McreWHIXonPokLEGO7n
 61Z1M9Q43333IZSAE+erop5CVJTOsFTf3Ox2RLroNg9MNFX1OiUuBrpSsG2O44BX
 59A0vQxIRuDqDgBDZapb0lpjj/E4pdyuKbBSZVDDKXbe9vWdhomibwMISiM9vjNm
 z8zy2lUA+qUE2UDSZFVFVDKk8hPwgSvcZfKhFUuuc3K+vXixNfxhFg7TVdH5RwkV
 pNgcXMuQjqPXz4k59MWS0E68aWPsvfsA3Xt/GD3yr4aSDskrzIiyc6F0u67mW1qG
 T1sQdzg2AHKXb7g774T2OW6ugeoEZ5LftDDZxTZx0+UIGk7JysXb9ksNJTqItnCI
 j4MSOK25EbHR/pk0cJAlCfn6kGYYOMzuTiOf+xEz4FvYHeduEAvUbT5irBMGkETI
 W4hwsv/fUPOhVMc4uYEZCIf6vcdLPDs9REvB55VGQm4O3CNM+ETBeRwnDHD8QaWg
 qPM8+vnrUjiE33YVPF0F/QhkJxSo+SZP79igwzpBva5ttkUuOpg=
 =p8rZ
 -----END PGP SIGNATURE-----

Merge tag 'linux-cpupower-6.7-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/shuah/linux

Merge cpupower utility update for 6.7-rc1 from Shuah Khan:

"This cpupower update for Linux 6.7-rc1 consists of a single fix to
 documentation to fix reference to a removed document."

* tag 'linux-cpupower-6.7-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/shuah/linux:
  cpupower: fix reference to nonexistent document
2023-11-03 15:30:10 +01:00
Varadarajan Narayanan
5b5b5806f2 cpufreq: qcom-nvmem: Introduce cpufreq for ipq95xx
IPQ95xx SoCs have different OPPs available for the CPU based on
the SoC variant. This can be determined from an eFuse register
present in the silicon.

Added support for ipq95xx on nvmem driver which helps to
determine OPPs at runtime based on the eFuse register which
has the CPU frequency limits. opp-supported-hw dt binding
can be used to indicate the available OPPs for each limit.

Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
Signed-off-by: Praveenkumar I <ipkumar@codeaurora.org>
Signed-off-by: Kathiravan T <quic_kathirav@quicinc.com>
Signed-off-by: Varadarajan Narayanan <quic_varada@quicinc.com>
[ Viresh: Fixed subject ]
Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
2023-11-02 11:04:53 +05:30
Varadarajan Narayanan
ba5a61a08d cpufreq: qcom-nvmem: Enable cpufreq for ipq53xx
IPQ53xx have different OPPs available for the CPU based on
SoC variant. This can be determined through use of an eFuse
register present in the silicon.

Added support for ipq53xx on nvmem driver which helps to
determine OPPs at runtime based on the eFuse register which
has the CPU frequency limits. opp-supported-hw dt binding
can be used to indicate the available OPPs for each limit.

nvmem driver also creates the "cpufreq-dt" platform_device after
passing the version matching data to the OPP framework so that the
cpufreq-dt handles the actual cpufreq implementation.

Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
Reviewed-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org>
Signed-off-by: Kathiravan T <quic_kathirav@quicinc.com>
Signed-off-by: Varadarajan Narayanan <quic_varada@quicinc.com>
[ Viresh: Fixed subject ]
Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
2023-11-02 11:04:53 +05:30
Robert Marko
0b9cd94913 cpufreq: qcom-nvmem: add support for IPQ8074
IPQ8074 comes in 3 families:
* IPQ8070A/IPQ8071A (Acorn) up to 1.4GHz
* IPQ8172/IPQ8173/IPQ8174 (Oak) up to 1.4GHz
* IPQ8072A/IPQ8074A/IPQ8076A/IPQ8078A (Hawkeye) up to 2.2GHz

So, in order to be able to share one OPP table lets add support for IPQ8074
family based of SMEM SoC ID-s as speedbin fuse is always 0 on IPQ8074.

IPQ8074 compatible is blacklisted from DT platdev as the cpufreq device
will get created by NVMEM CPUFreq driver.

Signed-off-by: Robert Marko <robimarko@gmail.com>
Acked-by: Konrad Dybcio <konrad.dybcio@linaro.org>
[ Viresh: Fixed rebase conflict. ]
Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
2023-11-02 11:04:53 +05:30
Viresh Kumar
477348dbfd Merge branch 'cpufreq/arm/qcom-nvmem' into HEAD
Merge base changes for cpufreq support for IPQ8074.
2023-11-02 11:04:33 +05:30
Dave Airlie
2ba446f821 drm: renesas: shmobile: Atomic conversion + DT support
Currently, there are two drivers for the LCD controller on Renesas
 SuperH-based and ARM-based SH-Mobile and R-Mobile SoCs:
   1. sh_mobile_lcdcfb, using the fbdev framework,
   2. shmob_drm, using the DRM framework.
 However, only the former driver is used, as all platform support
 integrates the former.  None of these drivers support DT-based systems.
 
 Convert the SH-Mobile DRM driver to atomic modesetting, and add DT
 support, complemented by the customary set of fixes and improvements.
 
 Acked-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
 Link: https://lore.kernel.org/r/cover.1694767208.git.geert+renesas@glider.be/
 -----BEGIN PGP SIGNATURE-----
 
 iHUEABYIAB0WIQQ9qaHoIs/1I4cXmEiKwlD9ZEnxcAUCZS0HuQAKCRCKwlD9ZEnx
 cI+KAP9PThUJqV7z1YxVeM/qYWYhqR4wezD18QCanCguAIvx9wD9F2ccIsFOso35
 iIv23N4D6gWJllaA2WBeKye3zYEjDQI=
 =RSnM
 -----END PGP SIGNATURE-----

Merge tag 'shmob-drm-atomic-dt-tag2' of git://git.kernel.org/pub/scm/linux/kernel/git/geert/renesas-drivers into drm-next

drm: renesas: shmobile: Atomic conversion + DT support

Currently, there are two drivers for the LCD controller on Renesas
SuperH-based and ARM-based SH-Mobile and R-Mobile SoCs:
  1. sh_mobile_lcdcfb, using the fbdev framework,
  2. shmob_drm, using the DRM framework.
However, only the former driver is used, as all platform support
integrates the former.  None of these drivers support DT-based systems.

Convert the SH-Mobile DRM driver to atomic modesetting, and add DT
support, complemented by the customary set of fixes and improvements.

Acked-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Link: https://lore.kernel.org/r/cover.1694767208.git.geert+renesas@glider.be/
Signed-off-by: Dave Airlie <airlied@redhat.com>

From: Geert Uytterhoeven <geert@linux-m68k.org>
Link: https://patchwork.freedesktop.org/patch/msgid/CAMuHMdUF61V5qNyKbrTGxZfEJvCVuLO7q2R5MqZYkzRC_cNr0w@mail.gmail.com
2023-11-02 11:52:55 +10:00
Yang Wang
2bfb0ca3dd drm/amdgpu: remove unused macro HW_REV
remove unused macro HW_REV

Signed-off-by: Yang Wang <kevinyang.wang@amd.com>
Reviewed-by: Kenneth Feng <kenneth.feng@amd.com>
Reviewed-by: Lijo Lazar <lijo.lazar@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
2023-10-31 17:13:59 -04:00
Ma Jun
7f3e6b840f drm/amd/pm: Fix error of MACO flag setting code
MACO only works if BACO is supported

Signed-off-by: Ma Jun <Jun.Ma2@amd.com>
Reviewed-by: Kenneth Feng <kenneth.feng@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Cc: stable@vger.kernel.org # 6.1.x
2023-10-31 17:13:13 -04:00
Arunpravin Paneer Selvam
9ae587f850 drm/amdgpu: Fix the vram base start address
If the size returned by drm buddy allocator is higher than
the required size, we take the higher size to calculate
the buffer start address. This is required if we couldn't
trim the buffer to the requested size. This will fix the
display corruption issue on APU's which has limited VRAM
size.

Link: https://gitlab.freedesktop.org/drm/amd/-/issues/2859
Fixes: 0a1844bf0b53 ("drm/buddy: Improve contiguous memory allocation")
Signed-off-by: Arunpravin Paneer Selvam <Arunpravin.PaneerSelvam@amd.com>
Acked-by: Christian König <christian.koenig@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
2023-10-31 17:10:13 -04:00
Tao Zhou
d539b0ad7c drm/amdgpu: set XGMI IP version manually for v6_4
The version can't be queried from discovery table.

Signed-off-by: Tao Zhou <tao.zhou1@amd.com>
Reviewed-by: Hawking Zhang <Hawking.Zhang@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
2023-10-31 17:09:53 -04:00
Tong Liu01
853eebe6ec drm/amdgpu: add unmap latency when gfx11 set kiq resources
[why]
If driver does not set unmap latency for KIQ, the default value of KIQ
unmap latency is zero. When do unmap queue, KIQ will return that almost
immediately after receiving unmap command. So, the queue status will be
saved to MQD incorrectly or lost in some chance.

[how]
Set unmap latency when do kiq set resources. The unmap latency is set to
be 1 second that is synchronized with Windows driver.

Acked-by: Alex Deucher <alexander.deucher@amd.com>
Signed-off-by: Tong Liu01 <Tong.Liu01@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
2023-10-31 16:40:16 -04:00
Kenneth Feng
5f38ac54e6 drm/amd/pm: fix the high voltage and temperature issue
fix the high voltage and temperature issue after the driver is unloaded on smu 13.0.0,
smu 13.0.7 and smu 13.0.10
v2 - fix the code format and make sure it is used on the unload case only.

Signed-off-by: Kenneth Feng <kenneth.feng@amd.com>
Reviewed-by: Yang Wang <kevinyang.wang@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
2023-10-31 16:40:16 -04:00
Yifan Zhang
a17f574ab4 drm/amdgpu: remove amdgpu_mes_self_test in gpu recover
gpu tlb flush is skipped if reset sem is held, it makes
mes_self_test fail since it involves add_hw_queue/remove_hw_queue
which needs tlb flush functional. Remove mes_self_test in gpu
recover sequence.

This patch is to fix the recover failure in gfx11.

[ 1831.768292] [drm] ring sdma_32769.3.3 was added
[ 1831.768313] [drm] ring gfx_32769.1.1 ib test pass
[ 1831.768337] [drm] ring compute_32769.2.2 ib test pass
[ 1831.768399] amdgpu 0000:c2:00.0: amdgpu: [gfxhub] page fault (src_id:0 ring:24 vmid:8 pasid:32769, for process  pid 0 thread  pid 0)
[ 1831.768434] amdgpu 0000:c2:00.0: amdgpu:   in page starting at address 0x0000aec200000000 from client 10
[ 1831.768456] amdgpu 0000:c2:00.0: amdgpu: GCVM_L2_PROTECTION_FAULT_STATUS:0x00800A30
[ 1831.768473] amdgpu 0000:c2:00.0: amdgpu:      Faulty UTCL2 client ID: CPC (0x5)
[ 1831.768489] amdgpu 0000:c2:00.0: amdgpu:      MORE_FAULTS: 0x0
[ 1831.768501] amdgpu 0000:c2:00.0: amdgpu:      WALKER_ERROR: 0x0
[ 1831.768513] amdgpu 0000:c2:00.0: amdgpu:      PERMISSION_FAULTS: 0x3
[ 1831.768521] amdgpu 0000:c2:00.0: amdgpu:      MAPPING_ERROR: 0x0
[ 1831.768529] amdgpu 0000:c2:00.0: amdgpu:      RW: 0x0
[ 1831.931229] amdgpu 0000:c2:00.0: [drm:amdgpu_ring_test_helper [amdgpu]] *ERROR* ring sdma_32769.3.3 test failed (-110)
[ 1832.062917] [drm:mes_v11_0_submit_pkt_and_poll_completion.constprop.0 [amdgpu]] *ERROR* MES failed to response msg=3
[ 1832.063107] [drm:amdgpu_mes_remove_hw_queue [amdgpu]] *ERROR* failed to remove hardware queue, queue id = 3

Fixes: e2e3788850b9 ("drm/amdgpu: rework lock handling for flush_tlb v2")
Reported-by: Li Ma <li.ma@amd.com>
Reviewed-by: Christian König <christian.koenig@amd.com>
Signed-off-by: Yifan Zhang <yifan1.zhang@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
2023-10-31 16:40:15 -04:00
Candice Li
e020d01575 drm/amdgpu: Drop deferred error in uncorrectable error check
Drop checking deferred error which can be handled by poison
consumption.

Signed-off-by: Candice Li <candice.li@amd.com>
Reviewed-by: Hawking Zhang <Hawking.Zhang@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
2023-10-31 16:40:15 -04:00
Lijo Lazar
5575ce2132 drm/amd/pm: Fix warnings
Fixes warnings:

drivers/gpu/drm/amd/amdgpu/../pm/swsmu/smu13/smu_v13_0_6_ppt.c:286:45:
warning: '%s' directive output may be truncated writing up to 29 bytes
into a region of size 23 [-Wformat-truncation=]
drivers/gpu/drm/amd/amdgpu/../pm/swsmu/smu13/smu_v13_0_6_ppt.c:286:52:
warning: '%s' directive output may be truncated writing up to 29 bytes
into a region of size 23 [-Wformat-truncation=]
drivers/gpu/drm/amd/amdgpu/../pm/swsmu/smu14/smu_v14_0.c:72:45: warning:
'%s' directive output may be truncated writing up to 29 bytes into a
region of size 23 [-Wformat-truncation=]
drivers/gpu/drm/amd/amdgpu/../pm/swsmu/smu14/smu_v14_0.c:72:52: warning:
'%s' directive output may be truncated writing up to 29 bytes into a
region of size 23 [-Wformat-truncation=]

Signed-off-by: Lijo Lazar <lijo.lazar@amd.com>
Reviewed-by: Yang Wang <kevinyang.wang@amd.com>
Reported-by: kernel test robot <lkp@intel.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
2023-10-31 16:40:15 -04:00
Tao Zhou
d1d4c0b7b6 drm/amdgpu: check RAS supported first in ras_reset_error_count
Not all platforms support RAS.

Fixes: 73582be11ac8 ("drm/amdgpu: bypass RAS error reset in some conditions")
Signed-off-by: Tao Zhou <tao.zhou1@amd.com>
Reviewed-by: Yang Wang <kevinyang.wang@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
2023-10-31 16:40:15 -04:00
Javier Martinez Canillas
94565e95e2
drm/ssd130x: Fix possible uninitialized usage of crtc_state variable
Avoid a possible uninitialized use of the crtc_state variable in function
ssd132x_primary_plane_atomic_check() and avoid the following Smatch warn:

    drivers/gpu/drm/solomon/ssd130x.c:921 ssd132x_primary_plane_atomic_check()
    error: uninitialized symbol 'crtc_state'.

Fixes: fdd591e00a9c ("drm/ssd130x: Add support for the SSD132x OLED controller family")
Reported-by: Dan Carpenter <dan.carpenter@linaro.org>
Closes: https://lore.kernel.org/dri-devel/7dd6ca45-8263-44fe-a318-2fd9d761425d@moroto.mountain/
Signed-off-by: Javier Martinez Canillas <javierm@redhat.com>
Acked-by: Jocelyn Falempe <jfalempe@redhat.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20231020225338.1686974-1-javierm@redhat.com
(cherry picked from commit 9e4db199e66d427c50458f4d72734cc4f0b92948)
Signed-off-by: Javier Martinez Canillas <javierm@redhat.com>
2023-10-30 11:00:27 +01:00
Javier Martinez Canillas
a49cf37d53
dt-bindings: display: ssd132x: Remove '-' before compatible enum
This is a leftover from when the binding schema had the compatible string
property enum as a 'oneOf' child and the '-' was not removed when 'oneOf'
got dropped during the binding review process.

Reported-by: Rob Herring <robh@kernel.org>
Closes: https://lore.kernel.org/dri-devel/CAL_Jsq+h8DcnpKqhokQOODCc8+Qi3M0PrxRFKz_Y4v37yMJvvA@mail.gmail.com/
Signed-off-by: Javier Martinez Canillas <javierm@redhat.com>
Acked-by: Conor Dooley <conor.dooley@microchip.com>
Reviewed-by: Rob Herring <robh@kernel.org>
Link: https://patchwork.freedesktop.org/patch/msgid/20231020223029.1667190-1-javierm@redhat.com
(cherry picked from commit 171c5f641031c0eee424ba79a3db4736c32e18ca)
Signed-off-by: Javier Martinez Canillas <javierm@redhat.com>
2023-10-30 10:59:11 +01:00
Vegard Nossum
6feb1a9641 cpupower: fix reference to nonexistent document
This file was renamed from .txt to .rst and left a dangling reference.
Fix it.

Fixes: 151f4e2bdc7a ("docs: power: convert docs to ReST and rename to *.rst")
Cc: Mauro Carvalho Chehab <mchehab+samsung@kernel.org>
Cc: Bjorn Helgaas <bhelgaas@google.com>
Cc: Mark Brown <broonie@kernel.org>
Cc: Srivatsa S. Bhat (VMware) <srivatsa@csail.mit.edu>
Cc: Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>
Cc: Jacob Pan <jacob.jun.pan@linux.intel.com>
Cc: Arjan van de Ven <arjan@linux.intel.com>
Cc: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Cc: Len Brown <len.brown@intel.com>
Signed-off-by: Vegard Nossum <vegard.nossum@oracle.com>
Signed-off-by: Shuah Khan <skhan@linuxfoundation.org>
2023-10-25 10:14:35 -06:00
Geert Uytterhoeven
1399ebacbf drm: renesas: shmobile: Add DT support
Add DT support, by:
  1. Creating a panel bridge from DT, and attaching it to the encoder,
  2. Replacing the custom connector with a bridge connector,
  3. Obtaining clock configuration based on the compatible value.

Note that for now the driver uses a fixed clock configuration selecting
the bus clock, as the current code to select other clock inputs needs
changes to support any other SoCs than SH7724.

Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
Link: https://lore.kernel.org/r/6185ab76aa300fa402e4f6610b2109665f2d8a1c.1694767209.git.geert+renesas@glider.be
2023-10-16 11:47:48 +02:00
Geert Uytterhoeven
b2b2f7ba8f drm: renesas: shmobile: Atomic conversion part 3
Complete the conversion to atomic mode setting by converting the
connector, and setting the DRIVER_ATOMIC flag.

Reviewed-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
Link: https://lore.kernel.org/r/042f9ff076c4b1c87235c74c8b76c9d161e126ec.1694767209.git.geert+renesas@glider.be
2023-10-16 11:47:48 +02:00
Geert Uytterhoeven
7c2d79f06e drm: renesas: shmobile: Remove internal CRTC state tracking
Now the suspend/resume methods no longer need to look at internal driver
state, the dpms and started fields in the shmob_drm_crtc structure can
be removed, as well as the shmob_drm_crtc_dpms() wrapper.  After this,
shmob_drm_crtc_atomic_{en,dis}able() became just wrappers around
shmob_drm_crtc_st{art,op}(), so inline the latter.

Reviewed-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
Link: https://lore.kernel.org/r/905b9ca72f43d40438c8cb1199cde140eb123204.1694767209.git.geert+renesas@glider.be
2023-10-16 11:47:47 +02:00
Geert Uytterhoeven
cc2c954668 drm: renesas: shmobile: Use suspend/resume helpers
Replace the custom suspend/resume handling by calls into
drm_mode_config_helper_{suspend,resume}().

Reviewed-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
Link: https://lore.kernel.org/r/a52147ca6033e0a59675f37f0326c7404fc5919c.1694767209.git.geert+renesas@glider.be
2023-10-16 11:47:47 +02:00
Geert Uytterhoeven
e3c8898b38 drm: renesas: shmobile: Atomic conversion part 2
Implement atomic mode setting for the CRTC, using the existing dpms
callback.

Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
Link: https://lore.kernel.org/r/ca2a00200ef5ac899a6131087d0a30de1c806119.1694767209.git.geert+renesas@glider.be
2023-10-16 11:47:47 +02:00
Geert Uytterhoeven
4afa041043 drm: renesas: shmobile: Atomic conversion part 1
Implement atomic mode setting for both the primary and overlay planes.
This involves:
  - Moving the primary plane handling code from CRTC mode setting to
    plane handling shared by primary and overlay planes,
  - Adding basic CRTC and mode config atomic mode setting ops, which
    don't do much yet.

Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
Link: https://lore.kernel.org/r/a6b698a1c8c1eaf631c2f928f5888ab5fe7aa4c3.1694767209.git.geert+renesas@glider.be
2023-10-16 11:47:47 +02:00
Geert Uytterhoeven
22a4414594 drm: renesas: shmobile: Cleanup encoder
Most unused callbacks can be NULL pointers these days.
Drop a bunch of empty encoder callbacks.

Reviewed-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
Link: https://lore.kernel.org/r/04f186573e1df90ecc051272f3d1cbe564c3469b.1694767209.git.geert+renesas@glider.be
2023-10-16 11:47:47 +02:00
Geert Uytterhoeven
fbe544ffc0 drm: renesas: shmobile: Shutdown the display on remove
When the device is unbound from the driver, the display may be active.
Make sure it gets shut down.

Reviewed-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
Link: https://lore.kernel.org/r/ddf2736459d59d0e961f240e77da7b0a28caae15.1694767209.git.geert+renesas@glider.be
2023-10-16 11:47:47 +02:00
Geert Uytterhoeven
c285aac128 drm: renesas: shmobile: Turn vblank on/off when enabling/disabling CRTC
The DRM core vblank handling mechanism requires drivers to forcefully
turn vblank reporting off when disabling the CRTC, and to restore the
vblank reporting status when enabling the CRTC.
Implement this using the drm_crtc_vblank_{on,off}() helpers.

Note that drm_crtc_vblank_off() must be called at startup to synchronize
the state of the vblank core code with the hardware, which is initially
disabled.  This is performed at CRTC creation time, requiring vertical
blank initialization to be moved before creating CRTCs.

Reviewed-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
Link: https://lore.kernel.org/r/e5833e5706b7792bfca8e6e56fc154a7c3e0574f.1694767209.git.geert+renesas@glider.be
2023-10-16 11:47:47 +02:00
Geert Uytterhoeven
b1ce7fe4c4 drm: renesas: shmobile: Wait for page flip when turning CRTC off
Turning a CRTC off will prevent a queued page flip from ever completing,
potentially confusing userspace.  Wait for queued page flips to complete
before turning the CRTC off to avoid this.

Reviewed-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
Link: https://lore.kernel.org/r/c97d5859c43fa36043c61de28d67688ebe345092.1694767209.git.geert+renesas@glider.be
2023-10-16 11:47:47 +02:00
Geert Uytterhoeven
a87e3159d4 drm: renesas: shmobile: Move shmob_drm_crtc_finish_page_flip()
Move the shmob_drm_crtc_finish_page_flip() function up, to avoid having
to move it during the modification in the next change.

Reviewed-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
Link: https://lore.kernel.org/r/4c87bb31403d142f8f146176cb859a10a28a3601.1694767209.git.geert+renesas@glider.be
2023-10-16 11:47:46 +02:00
Geert Uytterhoeven
03f716f61e drm: renesas: shmobile: Use drm_crtc_handle_vblank()
Replace the call to the legacy drm_handle_vblank() function with a call
to the new drm_crtc_handle_vblank() helper.

Reviewed-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
Reviewed-by: Sui Jingfeng <suijingfeng@loongson.cn>
Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
Link: https://lore.kernel.org/r/bef278cc9b7536505f41faaa2f13184d9354fa7e.1694767209.git.geert+renesas@glider.be
2023-10-16 11:47:46 +02:00
Geert Uytterhoeven
a83d383e1f drm: renesas: shmobile: Rename shmob_drm_plane.plane
Rename the "plane" member of the shmob_drm_plane subclass structure to
"base", to improve readability.

Reviewed-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
Reviewed-by: Sui Jingfeng <suijingfeng@loongson.cn>
Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
Link: https://lore.kernel.org/r/73809d0a94f9075dd868cf567790d10f8ae61603.1694767209.git.geert+renesas@glider.be
2023-10-16 11:47:46 +02:00
Geert Uytterhoeven
9d7bd3b12e drm: renesas: shmobile: Rename shmob_drm_connector.connector
Rename the "connector" member of the shmob_drm_connector subclass
structure to "base", to improve readability.

Reviewed-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
Reviewed-by: Sui Jingfeng <suijingfeng@loongson.cn>
Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
Link: https://lore.kernel.org/r/2382c4c796b53b5d2b24f99b85954ce632f21b90.1694767209.git.geert+renesas@glider.be
2023-10-16 11:47:46 +02:00
Geert Uytterhoeven
5195532484 drm: renesas: shmobile: Rename shmob_drm_crtc.crtc
Rename the "crtc" member of the shmob_drm_crtc subclass structure to
"base", to improve readability.

Reviewed-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
Reviewed-by: Sui Jingfeng <suijingfeng@loongson.cn>
Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
Link: https://lore.kernel.org/r/b42a32082d25bde6db7a57d8dc0d9f45820f6716.1694767209.git.geert+renesas@glider.be
2023-10-16 11:47:46 +02:00
Geert Uytterhoeven
c228823426 drm: renesas: shmobile: Unify plane allocation
Unify primary and overlay plane allocation:
  - Enhance shmob_drm_plane_create() so it can be used to create the
    primary plane, too,
  - Move overlay plane creation next to primary plane creation.

Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
Link: https://lore.kernel.org/r/adbc5febc0099fd1910f32a7af1c8e0f570f74b4.1694767209.git.geert+renesas@glider.be
2023-10-16 11:47:46 +02:00
Geert Uytterhoeven
adceac2cf1 drm: renesas: shmobile: Move interface handling to connector setup
Move legacy interface handling to the connector setup code.
Set up bus_flags and bus_formats in display_info according to the
bus format and panel information from platform data, to make it more
similar with DT-based connector/bridge/panel setup.
This will allow us to use the same LCD interface setup code for both
legacy and DT-based systems.

Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
Link: https://lore.kernel.org/r/912f615eb87c847804a268200ab57c63453c65d4.1694767209.git.geert+renesas@glider.be
2023-10-16 11:47:46 +02:00
Geert Uytterhoeven
fa32c6bc92 drm: renesas: shmobile: Use media bus formats in platform data
Replace the custom shmob_drm_interface enumeration values with standard
media bus formats.  This simplifies driver handling of bus formats and
prepares for DT support.

Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
Link: https://lore.kernel.org/r/0a15e5100ca30d14953c93550eb1d4c2e18de939.1694767209.git.geert+renesas@glider.be
2023-10-16 11:47:46 +02:00
Laurent Pinchart
6a6ab0c716 drm: renesas: shmobile: Use struct videomode in platform data
Replace the drm_mode_modeinfo field with videomode that includes more
signal polarity flags.  This simplifies driver handling of panel modes
and prepares for DT support.

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
[geert: Simplify]
Reviewed-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
Link: https://lore.kernel.org/r/4312e56de424d94399c6105e7159317eae86c9d5.1694767209.git.geert+renesas@glider.be
2023-10-16 11:47:46 +02:00
Geert Uytterhoeven
c2e938ee9a drm: renesas: shmobile: Replace .dev_private with container_of()
Now that drm_device is embedded in shmob_drm_device, we can use
a container_of()-based helper to get the shmob_drm_device pointer from
the drm_device, instead of using the deprecated drm_device.dev_private
field.

While at it, restore reverse Xmas tree ordering of local variable
declarations.

Reviewed-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
Reviewed-by: Sui Jingfeng <suijingfeng@loongson.cn>
Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
Link: https://lore.kernel.org/r/8ef4be8bffe75efc7f4b66f3732ec357f7d43e0f.1694767209.git.geert+renesas@glider.be
2023-10-16 11:47:45 +02:00
Geert Uytterhoeven
02e6c5b76f drm: renesas: shmobile: Convert container helpers to static inline functions
Replace to conversion helper macros using container_of() by static
inline functions, to improve type-safety.

Reviewed-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
Link: https://lore.kernel.org/r/7d1f1aa4b832499f9e527353ce0ad6d84ff9a74a.1694767209.git.geert+renesas@glider.be
2023-10-16 11:47:45 +02:00
Geert Uytterhoeven
5417750d5e drm: renesas: shmobile: Embed drm_device in shmob_drm_device
Embedding drm_device in shmob_drm_device allows us to use the DRM
managed API to allocate both structures in one go, simplifying error
handling.

Reviewed-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
Link: https://lore.kernel.org/r/abbf95021191824f44cc8c52e4afbde93d44363a.1694767209.git.geert+renesas@glider.be
2023-10-16 11:47:45 +02:00
Geert Uytterhoeven
3d77d2ac7d drm: renesas: shmobile: Use drmm_universal_plane_alloc()
According to the comments for drm_universal_plane_init(), the plane
structure should not be allocated with devm_kzalloc().

Fix lifetime issues by using drmm_universal_plane_alloc() instead.

Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
Link: https://lore.kernel.org/r/65ebf0513e2836227a9636e922f51c668bd69720.1694767209.git.geert+renesas@glider.be
2023-10-16 11:47:45 +02:00
Geert Uytterhoeven
33505f7718 drm: renesas: shmobile: Remove custom plane destroy callback
There is no need to call drm_plane_force_disable() from the plane's
.destroy() callback, as the plane should have been disabled already
before.  See also commit 3c858a33858baa8c ("drm/plane_helper: don't
disable plane in destroy function") for the generic plane helper case.

After removing this call, shmob_drm_plane_destroy() becomes a simple
wrapper around shmob_drm_plane_destroy(), hence replace it by the
latter.

Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
Link: https://lore.kernel.org/r/8d7a3f250612085fdf4e06d377843e8f874b22d9.1694767209.git.geert+renesas@glider.be
2023-10-16 11:47:45 +02:00
Geert Uytterhoeven
901500a8ba drm: renesas: shmobile: Convert to use devm_request_irq()
Convert to managed IRQ handling, to simplify cleanup.

Reviewed-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
Link: https://lore.kernel.org/r/8d870bdc59dd5e2754542388a03095ea09c96297.1694767209.git.geert+renesas@glider.be
2023-10-16 11:47:45 +02:00
Geert Uytterhoeven
95478b0828 drm: renesas: shmobile: Improve error handling
Prepare for DT conversion, where panel probe can be deferred, by
streamlining error propagation and handling:
  - Use dev_err_probe() to avoid printing error messages in case of
    probe deferral,
  - Propagate errors where needed.

Reviewed-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
Link: https://lore.kernel.org/r/6dfac76e5b1c7dda3f96801ce83845a4235e2ccd.1694767209.git.geert+renesas@glider.be
2023-10-16 11:47:45 +02:00
Laurent Pinchart
04ed052f3a drm: renesas: shmobile: Remove support for SYS panels
SYS panels are not used, and have no defined DT bindings.  Remove their
support to avoid impeding DT support.  It can always be added back
later.

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
Link: https://lore.kernel.org/r/4ccca2a5ac05c73ea9fd6e44b8bc443fd9d14e0d.1694767209.git.geert+renesas@glider.be
2023-10-16 11:47:45 +02:00
Laurent Pinchart
e2eb7e6ee5 drm: renesas: shmobile: Rename input clocks
Prepare for DT bindings by using more appropriate names for the input
clocks.

Note that all LDDCKR_ICKSEL_* definitions but the one for the bus clock
are valid only for SH7724, so the clock selection code needs to be
updated when extending clock support to other SoCs.

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
[geert: Add note]
Reviewed-by: Sui Jingfeng <suijingfeng@loongson.cn>
Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
Link: https://lore.kernel.org/r/d4b4d2164541ae055d10064103db3c2d6540e846.1694767209.git.geert+renesas@glider.be
2023-10-16 11:47:44 +02:00
Laurent Pinchart
76b1405832 drm: renesas: shmobile: Don't set display info width and height twice
The display info width_mm and height_mm fields are set at init time and
never overwritten, don't set them a second time when getting modes.

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
Reviewed-by: Sui Jingfeng <suijingfeng@loongson.cn>
Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
Link: https://lore.kernel.org/r/edd49fcb92af83d81df655b3db1685e8ed14380a.1694767209.git.geert+renesas@glider.be
2023-10-16 11:47:44 +02:00
Laurent Pinchart
0da28d5fc8 drm: renesas: shmobile: Remove backlight support
Backlight support should be implemented by panels, not by the LCDC
driver.  As the feature is currently unused anyway, remove it.

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
[geert: Cleanups]
Reviewed-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
Link: https://lore.kernel.org/r/69707650245bc2193d072f24723d4d5482ea590b.1694767209.git.geert+renesas@glider.be
2023-10-16 11:47:44 +02:00
Geert Uytterhoeven
7802ca6b23 drm: renesas: shmobile: Improve shmob_drm_format_info table
Improve the table containing hardware information related to the
supported plane formats:
  1. Move (part of) the overlay format register settings from multiple
     switch() statements spread across the code into the table, like is
     already done for the primary plane register settings,
  2. Remove the .yuv field, as that information can easily be extracted
     from the register settings using a new helper macro,
  3. Shrink and move the .bpp field to reduce table size.

Reviewed-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
Link: https://lore.kernel.org/r/b41f755e80ffe5fb4adbb2d8f96f2073de5c33bc.1694767209.git.geert+renesas@glider.be
2023-10-16 11:47:44 +02:00
Geert Uytterhoeven
02e6e3c2fa drm: renesas: shmobile: Add missing YCbCr formats
The primary plane supports various YCbCr formats, and the CRTC code
already knows how to handle them.  Enable support for the missing
formats by adding them to the table of supported modes.

Reviewed-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
Link: https://lore.kernel.org/r/e5a5d5ab2083280be5fcdc428e8b8ca198b4448d.1694767209.git.geert+renesas@glider.be
2023-10-16 11:47:44 +02:00
Geert Uytterhoeven
480b5571f3 drm: renesas: shmobile: Use %p4cc to print fourcc code
Replace the last printing of an hexadecimal fourcc format code by a
pretty-printed format name, using the "%p4cc" format specifier.

Reviewed-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
Link: https://lore.kernel.org/r/aaa9d474535f3cd800da5a9ef27023dc7960e690.1694767209.git.geert+renesas@glider.be
2023-10-16 11:47:44 +02:00
Geert Uytterhoeven
887042d635 drm: renesas: shmobile: Restore indentation of shmob_drm_setup_clocks()
Commit 56550d94cbaeaa19 ("Drivers: gpu: remove __dev* attributes.")
forgot to realign the continuation of the parameter section of
shmob_drm_setup_clocks().

Reviewed-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
Link: https://lore.kernel.org/r/b1c5c9b33b74fef1f4250847398a98f93c4dc1be.1694767209.git.geert+renesas@glider.be
2023-10-16 11:47:44 +02:00
Geert Uytterhoeven
616f73c9d3 drm: renesas: shmobile: Add support for Runtime PM
The SH-Mobile LCD Controller is part of a PM Domain on all relevant SoCs
(clock domain on all, power domain on some).  Hence it may not be
sufficient to manage the LCDC module clock explicitly (e.g. if the
selected clock source differs from SHMOB_DRM_CLK_BUS).

Fix this by using Runtime PM for all clock handling.  Add an explicit
dependency on CONFIG_PM, which should already be met on all affected
platforms.

Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
Link: https://lore.kernel.org/r/e7359a64963bd9a4f1531c2beae850774ce140bc.1694767209.git.geert+renesas@glider.be
2023-10-16 11:47:43 +02:00
Geert Uytterhoeven
b25064ef99 drm: renesas: shmobile: Correct encoder/connector types
The first encoder output on the SH-Mobile LCD Controller is a DPI
parallel bus.  However, at the time of introduction of the driver, no
encoder or connector types were defined yet for the DPI parallel bus,
hence the driver used the ones for LVDS instead.

Adjust the types accordingly.

Reviewed-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
Link: https://lore.kernel.org/r/db500dd8356955d3471a1ccd68d90db9f9750ef9.1694767209.git.geert+renesas@glider.be
2023-10-16 11:47:43 +02:00
Geert Uytterhoeven
1396c2693a drm: renesas: shmobile: Fix ARGB32 overlay format typo
When configuring a CHn Source Image Format Register (LDBBSIFR), one
should use the corresponding LDBBSIFR_RPKF_* definition for overlay
planes, not the DDFR_PKF_* definition for the primary plane.

Fortunately both definitions resolve to the same value, so this bug did
not cause any harm.

Reviewed-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
Link: https://lore.kernel.org/r/34f8d51539c048e264699ca869ad9d7a952cd69f.1694767209.git.geert+renesas@glider.be
2023-10-16 11:47:43 +02:00
Geert Uytterhoeven
28675d45a3 drm: renesas: shmobile: Fix overlay plane disable
Merely writing zero to the CHn Source Image Format Register is not
sufficient to disable a plane, as the programmed register value is not
propagated immediately to the current side.  This can be seen when using
the -P option of modetest: the extra plane is displayed correctly, but
does not disappear after exit.

Fix this by doing the full update dance using the Blend Control
Register, like is done when enabling the plane.

Reviewed-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
Link: https://lore.kernel.org/r/54e2556e18b5524ce153a7ac79faf2c7b0a55260.1694767209.git.geert+renesas@glider.be
2023-10-16 11:47:43 +02:00
Geert Uytterhoeven
c68ab8b5ea media: uapi: Add MEDIA_BUS_FMT_RGB666_2X9_BE format
Add the RGB666 9:9 format MEDIA_BUS_FMT_RGB666_2X9_BE, which is
supported by the SH-Mobile LCD Controller.

Reviewed-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
Link: https://lore.kernel.org/r/8b421cc391ac511c07cb1e243c1ba18bb95f7f98.1694767209.git.geert+renesas@glider.be
2023-10-16 11:47:43 +02:00
Geert Uytterhoeven
613676ec42 dt-bindings: display: Add Renesas SH-Mobile LCDC bindings
Add device tree bindings for the LCD Controller (LCDC) found in Renesas
SuperH SH-Mobile and ARM SH/R-Mobile SOCs.

Based on a plain text prototype by Laurent Pinchart.

Reviewed-by: Rob Herring <robh@kernel.org>
Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
Link: https://lore.kernel.org/r/6d0a053502abd6555e9a6cbe055e1bdc3329999d.1694767208.git.geert+renesas@glider.be
2023-10-16 11:47:43 +02:00
Geert Uytterhoeven
406a849926 MAINTAINER: Create entry for Renesas SH-Mobile DRM drivers
Split off DRM drivers for Renesas SH-Mobile into its own entry, and add
Geert Uytterhoeven as a maintainer.

Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
Link: https://lore.kernel.org/r/7cbcec72214886b67afa8d724a9245661d8cd675.1694767208.git.geert+renesas@glider.be
2023-10-16 11:47:43 +02:00
75 changed files with 1794 additions and 1358 deletions

View File

@ -0,0 +1,130 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/display/renesas,shmobile-lcdc.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Renesas SH-Mobile LCD Controller (LCDC)
maintainers:
- Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
- Geert Uytterhoeven <geert+renesas@glider.be>
properties:
compatible:
enum:
- renesas,r8a7740-lcdc # R-Mobile A1
- renesas,sh73a0-lcdc # SH-Mobile AG5
reg:
maxItems: 1
interrupts:
maxItems: 1
clocks:
minItems: 1
maxItems: 5
description:
Only the functional clock is mandatory.
Some of the optional clocks are model-dependent (e.g. "video" (a.k.a.
"vou" or "dv_clk") is available on R-Mobile A1 only).
clock-names:
minItems: 1
items:
- const: fck
- enum: [ media, lclk, hdmi, video ]
- enum: [ media, lclk, hdmi, video ]
- enum: [ media, lclk, hdmi, video ]
- enum: [ media, lclk, hdmi, video ]
power-domains:
maxItems: 1
ports:
$ref: /schemas/graph.yaml#/properties/ports
properties:
port@0:
$ref: /schemas/graph.yaml#/properties/port
description: LCD port (R-Mobile A1 and SH-Mobile AG5)
unevaluatedProperties: false
port@1:
$ref: /schemas/graph.yaml#/properties/port
description: HDMI port (R-Mobile A1 LCDC1 and SH-Mobile AG5)
unevaluatedProperties: false
port@2:
$ref: /schemas/graph.yaml#/properties/port
description: MIPI-DSI port (SH-Mobile AG5)
unevaluatedProperties: false
required:
- port@0
unevaluatedProperties: false
required:
- compatible
- reg
- interrupts
- clocks
- clock-names
- power-domains
- ports
additionalProperties: false
allOf:
- if:
properties:
compatible:
contains:
const: renesas,r8a7740-lcdc
then:
properties:
ports:
properties:
port@2: false
- if:
properties:
compatible:
contains:
const: renesas,sh73a0-lcdc
then:
properties:
ports:
required:
- port@1
- port@2
examples:
- |
#include <dt-bindings/clock/r8a7740-clock.h>
#include <dt-bindings/interrupt-controller/arm-gic.h>
lcd-controller@fe940000 {
compatible = "renesas,r8a7740-lcdc";
reg = <0xfe940000 0x4000>;
interrupts = <GIC_SPI 177 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&mstp1_clks R8A7740_CLK_LCDC0>,
<&cpg_clocks R8A7740_CLK_M3>, <&lcdlclk0_clk>,
<&vou_clk>;
clock-names = "fck", "media", "lclk", "video";
power-domains = <&pd_a4lc>;
ports {
#address-cells = <1>;
#size-cells = <0>;
port@0 {
reg = <0>;
lcdc0_rgb: endpoint {
};
};
};
};

View File

@ -11,10 +11,10 @@ maintainers:
properties:
compatible:
- enum:
- solomon,ssd1322
- solomon,ssd1325
- solomon,ssd1327
enum:
- solomon,ssd1322
- solomon,ssd1325
- solomon,ssd1327
required:
- compatible

View File

@ -949,6 +949,78 @@ The following tables list existing packed RGB formats.
- b\ :sub:`2`
- b\ :sub:`1`
- b\ :sub:`0`
* .. _MEDIA-BUS-FMT-RGB666-2X9-BE:
- MEDIA_BUS_FMT_RGB666_2X9_BE
- 0x1025
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- r\ :sub:`5`
- r\ :sub:`4`
- r\ :sub:`3`
- r\ :sub:`2`
- r\ :sub:`1`
- r\ :sub:`0`
- g\ :sub:`5`
- g\ :sub:`4`
- g\ :sub:`3`
* -
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- g\ :sub:`2`
- g\ :sub:`1`
- g\ :sub:`0`
- b\ :sub:`5`
- b\ :sub:`4`
- b\ :sub:`3`
- b\ :sub:`2`
- b\ :sub:`1`
- b\ :sub:`0`
* .. _MEDIA-BUS-FMT-BGR666-1X18:
- MEDIA_BUS_FMT_BGR666_1X18

View File

@ -7133,7 +7133,7 @@ F: drivers/gpu/host1x/
F: include/linux/host1x.h
F: include/uapi/drm/tegra_drm.h
DRM DRIVERS FOR RENESAS
DRM DRIVERS FOR RENESAS R-CAR
M: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
M: Kieran Bingham <kieran.bingham+renesas@ideasonboard.com>
L: dri-devel@lists.freedesktop.org
@ -7144,7 +7144,16 @@ F: Documentation/devicetree/bindings/display/bridge/renesas,dsi-csi2-tx.yaml
F: Documentation/devicetree/bindings/display/bridge/renesas,dw-hdmi.yaml
F: Documentation/devicetree/bindings/display/bridge/renesas,lvds.yaml
F: Documentation/devicetree/bindings/display/renesas,du.yaml
F: drivers/gpu/drm/renesas/
F: drivers/gpu/drm/renesas/rcar-du/
DRM DRIVERS FOR RENESAS SHMOBILE
M: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
M: Geert Uytterhoeven <geert+renesas@glider.be>
L: dri-devel@lists.freedesktop.org
L: linux-renesas-soc@vger.kernel.org
S: Supported
F: Documentation/devicetree/bindings/display/renesas,shmobile-lcdc.yaml
F: drivers/gpu/drm/renesas/shmobile/
F: include/linux/platform_data/shmob_drm.h
DRM DRIVERS FOR ROCKCHIP

View File

@ -180,8 +180,11 @@ static const struct of_device_id blocklist[] __initconst = {
{ .compatible = "ti,am62a7", },
{ .compatible = "ti,am62p5", },
{ .compatible = "qcom,ipq5332", },
{ .compatible = "qcom,ipq6018", },
{ .compatible = "qcom,ipq8064", },
{ .compatible = "qcom,ipq8074", },
{ .compatible = "qcom,ipq9574", },
{ .compatible = "qcom,apq8064", },
{ .compatible = "qcom,msm8974", },
{ .compatible = "qcom,msm8960", },

View File

@ -38,6 +38,11 @@ enum ipq806x_versions {
#define IPQ6000_VERSION BIT(2)
enum ipq8074_versions {
IPQ8074_HAWKEYE_VERSION = 0,
IPQ8074_ACORN_VERSION,
};
struct qcom_cpufreq_drv;
struct qcom_cpufreq_match_data {
@ -178,6 +183,16 @@ static int qcom_cpufreq_kryo_name_version(struct device *cpu_dev,
switch (msm_id) {
case QCOM_ID_MSM8996:
case QCOM_ID_APQ8096:
case QCOM_ID_IPQ5332:
case QCOM_ID_IPQ5322:
case QCOM_ID_IPQ5312:
case QCOM_ID_IPQ5302:
case QCOM_ID_IPQ5300:
case QCOM_ID_IPQ9514:
case QCOM_ID_IPQ9550:
case QCOM_ID_IPQ9554:
case QCOM_ID_IPQ9570:
case QCOM_ID_IPQ9574:
drv->versions = 1 << (unsigned int)(*speedbin);
break;
case QCOM_ID_MSM8996SG:
@ -338,6 +353,44 @@ static int qcom_cpufreq_ipq6018_name_version(struct device *cpu_dev,
return 0;
}
static int qcom_cpufreq_ipq8074_name_version(struct device *cpu_dev,
struct nvmem_cell *speedbin_nvmem,
char **pvs_name,
struct qcom_cpufreq_drv *drv)
{
u32 msm_id;
int ret;
*pvs_name = NULL;
ret = qcom_smem_get_soc_id(&msm_id);
if (ret)
return ret;
switch (msm_id) {
case QCOM_ID_IPQ8070A:
case QCOM_ID_IPQ8071A:
case QCOM_ID_IPQ8172:
case QCOM_ID_IPQ8173:
case QCOM_ID_IPQ8174:
drv->versions = BIT(IPQ8074_ACORN_VERSION);
break;
case QCOM_ID_IPQ8072A:
case QCOM_ID_IPQ8074A:
case QCOM_ID_IPQ8076A:
case QCOM_ID_IPQ8078A:
drv->versions = BIT(IPQ8074_HAWKEYE_VERSION);
break;
default:
dev_err(cpu_dev,
"SoC ID %u is not part of IPQ8074 family, limiting to 1.4GHz!\n",
msm_id);
drv->versions = BIT(IPQ8074_ACORN_VERSION);
break;
}
return 0;
}
static const char *generic_genpd_names[] = { "perf", NULL };
static const struct qcom_cpufreq_match_data match_data_kryo = {
@ -367,6 +420,10 @@ static const struct qcom_cpufreq_match_data match_data_ipq8064 = {
.get_version = qcom_cpufreq_ipq8064_name_version,
};
static const struct qcom_cpufreq_match_data match_data_ipq8074 = {
.get_version = qcom_cpufreq_ipq8074_name_version,
};
static int qcom_cpufreq_probe(struct platform_device *pdev)
{
struct qcom_cpufreq_drv *drv;
@ -494,9 +551,12 @@ static const struct of_device_id qcom_cpufreq_match_list[] __initconst = {
{ .compatible = "qcom,msm8909", .data = &match_data_msm8909 },
{ .compatible = "qcom,msm8996", .data = &match_data_kryo },
{ .compatible = "qcom,qcs404", .data = &match_data_qcs404 },
{ .compatible = "qcom,ipq5332", .data = &match_data_kryo },
{ .compatible = "qcom,ipq6018", .data = &match_data_ipq6018 },
{ .compatible = "qcom,ipq8064", .data = &match_data_ipq8064 },
{ .compatible = "qcom,ipq8074", .data = &match_data_ipq8074 },
{ .compatible = "qcom,apq8064", .data = &match_data_krait },
{ .compatible = "qcom,ipq9574", .data = &match_data_kryo },
{ .compatible = "qcom,msm8974", .data = &match_data_krait },
{ .compatible = "qcom,msm8960", .data = &match_data_krait },
{},

View File

@ -363,9 +363,6 @@ struct amdgpu_ip_block_version {
const struct amd_ip_funcs *funcs;
};
#define HW_REV(_Major, _Minor, _Rev) \
((((uint32_t) (_Major)) << 16) | ((uint32_t) (_Minor) << 8) | ((uint32_t) (_Rev)))
struct amdgpu_ip_block {
struct amdgpu_ip_block_status status;
const struct amdgpu_ip_block_version *version;

View File

@ -425,6 +425,32 @@ validate_fail:
return ret;
}
static int amdgpu_amdkfd_bo_validate_and_fence(struct amdgpu_bo *bo,
uint32_t domain,
struct dma_fence *fence)
{
int ret = amdgpu_bo_reserve(bo, false);
if (ret)
return ret;
ret = amdgpu_amdkfd_bo_validate(bo, domain, true);
if (ret)
goto unreserve_out;
ret = dma_resv_reserve_fences(bo->tbo.base.resv, 1);
if (ret)
goto unreserve_out;
dma_resv_add_fence(bo->tbo.base.resv, fence,
DMA_RESV_USAGE_BOOKKEEP);
unreserve_out:
amdgpu_bo_unreserve(bo);
return ret;
}
static int amdgpu_amdkfd_validate_vm_bo(void *_unused, struct amdgpu_bo *bo)
{
return amdgpu_amdkfd_bo_validate(bo, bo->allowed_domains, false);
@ -1784,6 +1810,15 @@ int amdgpu_amdkfd_gpuvm_alloc_memory_of_gpu(
}
bo->allowed_domains = AMDGPU_GEM_DOMAIN_GTT;
bo->preferred_domains = AMDGPU_GEM_DOMAIN_GTT;
} else {
mutex_lock(&avm->process_info->lock);
if (avm->process_info->eviction_fence &&
!dma_fence_is_signaled(&avm->process_info->eviction_fence->base))
ret = amdgpu_amdkfd_bo_validate_and_fence(bo, domain,
&avm->process_info->eviction_fence->base);
mutex_unlock(&avm->process_info->lock);
if (ret)
goto err_validate_bo;
}
if (offset)
@ -1793,6 +1828,7 @@ int amdgpu_amdkfd_gpuvm_alloc_memory_of_gpu(
allocate_init_user_pages_failed:
err_pin_bo:
err_validate_bo:
remove_kgd_mem_from_kfd_bo_list(*mem, avm->process_info);
drm_vma_node_revoke(&gobj->vma_node, drm_priv);
err_node_allow:
@ -1866,10 +1902,6 @@ int amdgpu_amdkfd_gpuvm_free_memory_of_gpu(
if (unlikely(ret))
return ret;
/* The eviction fence should be removed by the last unmap.
* TODO: Log an error condition if the bo still has the eviction fence
* attached
*/
amdgpu_amdkfd_remove_eviction_fence(mem->bo,
process_info->eviction_fence);
pr_debug("Release VA 0x%llx - 0x%llx\n", mem->va,
@ -1998,19 +2030,6 @@ int amdgpu_amdkfd_gpuvm_map_memory_to_gpu(
if (unlikely(ret))
goto out_unreserve;
if (mem->mapped_to_gpu_memory == 0 &&
!amdgpu_ttm_tt_get_usermm(bo->tbo.ttm)) {
/* Validate BO only once. The eviction fence gets added to BO
* the first time it is mapped. Validate will wait for all
* background evictions to complete.
*/
ret = amdgpu_amdkfd_bo_validate(bo, domain, true);
if (ret) {
pr_debug("Validate failed\n");
goto out_unreserve;
}
}
list_for_each_entry(entry, &mem->attachments, list) {
if (entry->bo_va->base.vm != avm || entry->is_mapped)
continue;
@ -2037,10 +2056,6 @@ int amdgpu_amdkfd_gpuvm_map_memory_to_gpu(
mem->mapped_to_gpu_memory);
}
if (!amdgpu_ttm_tt_get_usermm(bo->tbo.ttm) && !bo->tbo.pin_count)
dma_resv_add_fence(bo->tbo.base.resv,
&avm->process_info->eviction_fence->base,
DMA_RESV_USAGE_BOOKKEEP);
ret = unreserve_bo_and_vms(&ctx, false, false);
goto out;
@ -2074,7 +2089,6 @@ int amdgpu_amdkfd_gpuvm_unmap_memory_from_gpu(
struct amdgpu_device *adev, struct kgd_mem *mem, void *drm_priv)
{
struct amdgpu_vm *avm = drm_priv_to_vm(drm_priv);
struct amdkfd_process_info *process_info = avm->process_info;
unsigned long bo_size = mem->bo->tbo.base.size;
struct kfd_mem_attachment *entry;
struct bo_vm_reservation_context ctx;
@ -2115,15 +2129,6 @@ int amdgpu_amdkfd_gpuvm_unmap_memory_from_gpu(
mem->mapped_to_gpu_memory);
}
/* If BO is unmapped from all VMs, unfence it. It can be evicted if
* required.
*/
if (mem->mapped_to_gpu_memory == 0 &&
!amdgpu_ttm_tt_get_usermm(mem->bo->tbo.ttm) &&
!mem->bo->tbo.pin_count)
amdgpu_amdkfd_remove_eviction_fence(mem->bo,
process_info->eviction_fence);
unreserve_out:
unreserve_bo_and_vms(&ctx, false, false);
out:
@ -2351,8 +2356,20 @@ int amdgpu_amdkfd_gpuvm_import_dmabuf(struct amdgpu_device *adev,
amdgpu_sync_create(&(*mem)->sync);
(*mem)->is_imported = true;
mutex_lock(&avm->process_info->lock);
if (avm->process_info->eviction_fence &&
!dma_fence_is_signaled(&avm->process_info->eviction_fence->base))
ret = amdgpu_amdkfd_bo_validate_and_fence(bo, (*mem)->domain,
&avm->process_info->eviction_fence->base);
mutex_unlock(&avm->process_info->lock);
if (ret)
goto err_remove_mem;
return 0;
err_remove_mem:
remove_kgd_mem_from_kfd_bo_list(*mem, avm->process_info);
drm_vma_node_revoke(&obj->vma_node, drm_priv);
err_free_mem:
kfree(*mem);
err_put_obj:

View File

@ -29,6 +29,7 @@
#include "amdgpu.h"
#include "atom.h"
#include <linux/device.h>
#include <linux/pci.h>
#include <linux/slab.h>
#include <linux/acpi.h>
@ -287,6 +288,10 @@ static bool amdgpu_atrm_get_bios(struct amdgpu_device *adev)
if (adev->flags & AMD_IS_APU)
return false;
/* ATRM is for on-platform devices only */
if (dev_is_removable(&adev->pdev->dev))
return false;
while ((pdev = pci_get_base_class(PCI_BASE_CLASS_DISPLAY, pdev))) {
if ((pdev->class != PCI_CLASS_DISPLAY_VGA << 8) &&
(pdev->class != PCI_CLASS_DISPLAY_OTHER << 8))

View File

@ -1117,6 +1117,11 @@ static int amdgpu_cs_vm_handling(struct amdgpu_cs_parser *p)
return r;
}
/* FIXME: In theory this loop shouldn't be needed any more when
* amdgpu_vm_handle_moved handles all moved BOs that are reserved
* with p->ticket. But removing it caused test regressions, so I'm
* leaving it here for now.
*/
amdgpu_bo_list_for_each_entry(e, p->bo_list) {
bo_va = e->bo_va;
if (bo_va == NULL)
@ -1131,7 +1136,7 @@ static int amdgpu_cs_vm_handling(struct amdgpu_cs_parser *p)
return r;
}
r = amdgpu_vm_handle_moved(adev, vm);
r = amdgpu_vm_handle_moved(adev, vm, &p->exec.ticket);
if (r)
return r;

View File

@ -41,6 +41,7 @@
#include <drm/drm_fb_helper.h>
#include <drm/drm_probe_helper.h>
#include <drm/amdgpu_drm.h>
#include <linux/device.h>
#include <linux/vgaarb.h>
#include <linux/vga_switcheroo.h>
#include <linux/efi.h>
@ -1073,6 +1074,8 @@ static int amdgpu_device_asic_init(struct amdgpu_device *adev)
amdgpu_ip_version(adev, GC_HWIP, 0) >= IP_VERSION(11, 0, 0)) {
amdgpu_psp_wait_for_bootloader(adev);
ret = amdgpu_atomfirmware_asic_init(adev, true);
/* TODO: check the return val and stop device initialization if boot fails */
amdgpu_psp_query_boot_status(adev);
return ret;
} else {
return amdgpu_atom_asic_init(adev->mode_info.atom_context);
@ -2223,7 +2226,6 @@ out:
*/
static int amdgpu_device_ip_early_init(struct amdgpu_device *adev)
{
struct drm_device *dev = adev_to_drm(adev);
struct pci_dev *parent;
int i, r;
bool total;
@ -2294,7 +2296,7 @@ static int amdgpu_device_ip_early_init(struct amdgpu_device *adev)
(amdgpu_is_atpx_hybrid() ||
amdgpu_has_atpx_dgpu_power_cntl()) &&
((adev->flags & AMD_IS_APU) == 0) &&
!pci_is_thunderbolt_attached(to_pci_dev(dev->dev)))
!dev_is_removable(&adev->pdev->dev))
adev->flags |= AMD_IS_PX;
if (!(adev->flags & AMD_IS_APU)) {
@ -3962,13 +3964,23 @@ int amdgpu_device_init(struct amdgpu_device *adev,
}
}
} else {
tmp = amdgpu_reset_method;
/* It should do a default reset when loading or reloading the driver,
* regardless of the module parameter reset_method.
*/
amdgpu_reset_method = AMD_RESET_METHOD_NONE;
r = amdgpu_asic_reset(adev);
amdgpu_reset_method = tmp;
switch (amdgpu_ip_version(adev, MP1_HWIP, 0)) {
case IP_VERSION(13, 0, 0):
case IP_VERSION(13, 0, 7):
case IP_VERSION(13, 0, 10):
r = psp_gpu_reset(adev);
break;
default:
tmp = amdgpu_reset_method;
/* It should do a default reset when loading or reloading the driver,
* regardless of the module parameter reset_method.
*/
amdgpu_reset_method = AMD_RESET_METHOD_NONE;
r = amdgpu_asic_reset(adev);
amdgpu_reset_method = tmp;
break;
}
if (r) {
dev_err(adev->dev, "asic reset on init failed\n");
goto failed;
@ -4132,7 +4144,7 @@ fence_driver_init:
px = amdgpu_device_supports_px(ddev);
if (px || (!pci_is_thunderbolt_attached(adev->pdev) &&
if (px || (!dev_is_removable(&adev->pdev->dev) &&
apple_gmux_detect(NULL, NULL)))
vga_switcheroo_register_client(adev->pdev,
&amdgpu_switcheroo_ops, px);
@ -4282,7 +4294,7 @@ void amdgpu_device_fini_sw(struct amdgpu_device *adev)
px = amdgpu_device_supports_px(adev_to_drm(adev));
if (px || (!pci_is_thunderbolt_attached(adev->pdev) &&
if (px || (!dev_is_removable(&adev->pdev->dev) &&
apple_gmux_detect(NULL, NULL)))
vga_switcheroo_unregister_client(adev->pdev);
@ -5566,10 +5578,6 @@ skip_hw_reset:
drm_sched_start(&ring->sched, true);
}
if (adev->enable_mes &&
amdgpu_ip_version(adev, GC_HWIP, 0) != IP_VERSION(11, 0, 3))
amdgpu_mes_self_test(tmp_adev);
if (!drm_drv_uses_atomic_modeset(adev_to_drm(tmp_adev)) && !job_signaled)
drm_helper_resume_force_mode(adev_to_drm(tmp_adev));

View File

@ -99,6 +99,7 @@
MODULE_FIRMWARE(FIRMWARE_IP_DISCOVERY);
#define mmRCC_CONFIG_MEMSIZE 0xde3
#define mmMP0_SMN_C2PMSG_33 0x16061
#define mmMM_INDEX 0x0
#define mmMM_INDEX_HI 0x6
#define mmMM_DATA 0x1
@ -239,8 +240,26 @@ static int amdgpu_discovery_read_binary_from_sysmem(struct amdgpu_device *adev,
static int amdgpu_discovery_read_binary_from_mem(struct amdgpu_device *adev,
uint8_t *binary)
{
uint64_t vram_size = (uint64_t)RREG32(mmRCC_CONFIG_MEMSIZE) << 20;
int ret = 0;
uint64_t vram_size;
u32 msg;
int i, ret = 0;
/* It can take up to a second for IFWI init to complete on some dGPUs,
* but generally it should be in the 60-100ms range. Normally this starts
* as soon as the device gets power so by the time the OS loads this has long
* completed. However, when a card is hotplugged via e.g., USB4, we need to
* wait for this to complete. Once the C2PMSG is updated, we can
* continue.
*/
if (dev_is_removable(&adev->pdev->dev)) {
for (i = 0; i < 1000; i++) {
msg = RREG32(mmMP0_SMN_C2PMSG_33);
if (msg & 0x80000000)
break;
msleep(1);
}
}
vram_size = (uint64_t)RREG32(mmRCC_CONFIG_MEMSIZE) << 20;
if (vram_size) {
uint64_t pos = vram_size - DISCOVERY_TMR_OFFSET;
@ -2449,6 +2468,9 @@ int amdgpu_discovery_set_ip_blocks(struct amdgpu_device *adev)
if (amdgpu_ip_version(adev, XGMI_HWIP, 0) == IP_VERSION(4, 8, 0))
adev->gmc.xgmi.supported = true;
if (amdgpu_ip_version(adev, GC_HWIP, 0) == IP_VERSION(9, 4, 3))
adev->ip_versions[XGMI_HWIP][0] = IP_VERSION(6, 4, 0);
/* set NBIO version */
switch (amdgpu_ip_version(adev, NBIO_HWIP, 0)) {
case IP_VERSION(6, 1, 0):

View File

@ -409,7 +409,7 @@ amdgpu_dma_buf_move_notify(struct dma_buf_attachment *attach)
if (!r)
r = amdgpu_vm_clear_freed(adev, vm, NULL);
if (!r)
r = amdgpu_vm_handle_moved(adev, vm);
r = amdgpu_vm_handle_moved(adev, vm, ticket);
if (r && r != -EBUSY)
DRM_ERROR("Failed to invalidate VM page tables (%d))\n",

View File

@ -2041,6 +2041,14 @@ static const struct pci_device_id pciidlist[] = {
MODULE_DEVICE_TABLE(pci, pciidlist);
static const struct amdgpu_asic_type_quirk asic_type_quirks[] = {
/* differentiate between P10 and P11 asics with the same DID */
{0x67FF, 0xE3, CHIP_POLARIS10},
{0x67FF, 0xE7, CHIP_POLARIS10},
{0x67FF, 0xF3, CHIP_POLARIS10},
{0x67FF, 0xF7, CHIP_POLARIS10},
};
static const struct drm_driver amdgpu_kms_driver;
static void amdgpu_get_secondary_funcs(struct amdgpu_device *adev)
@ -2083,6 +2091,22 @@ static void amdgpu_init_debug_options(struct amdgpu_device *adev)
}
}
static unsigned long amdgpu_fix_asic_type(struct pci_dev *pdev, unsigned long flags)
{
int i;
for (i = 0; i < ARRAY_SIZE(asic_type_quirks); i++) {
if (pdev->device == asic_type_quirks[i].device &&
pdev->revision == asic_type_quirks[i].revision) {
flags &= ~AMD_ASIC_MASK;
flags |= asic_type_quirks[i].type;
break;
}
}
return flags;
}
static int amdgpu_pci_probe(struct pci_dev *pdev,
const struct pci_device_id *ent)
{
@ -2110,15 +2134,8 @@ static int amdgpu_pci_probe(struct pci_dev *pdev,
"See modparam exp_hw_support\n");
return -ENODEV;
}
/* differentiate between P10 and P11 asics with the same DID */
if (pdev->device == 0x67FF &&
(pdev->revision == 0xE3 ||
pdev->revision == 0xE7 ||
pdev->revision == 0xF3 ||
pdev->revision == 0xF7)) {
flags &= ~AMD_ASIC_MASK;
flags |= CHIP_POLARIS10;
}
flags = amdgpu_fix_asic_type(pdev, flags);
/* Due to hardware bugs, S/G Display on raven requires a 1:1 IOMMU mapping,
* however, SME requires an indirect IOMMU mapping because the encryption

View File

@ -385,9 +385,11 @@ int amdgpu_gfx_mqd_sw_init(struct amdgpu_device *adev,
struct amdgpu_ring *ring = &kiq->ring;
u32 domain = AMDGPU_GEM_DOMAIN_GTT;
#if !defined(CONFIG_ARM) && !defined(CONFIG_ARM64)
/* Only enable on gfx10 and 11 for now to avoid changing behavior on older chips */
if (amdgpu_ip_version(adev, GC_HWIP, 0) >= IP_VERSION(10, 0, 0))
domain |= AMDGPU_GEM_DOMAIN_VRAM;
#endif
/* create MQD for KIQ */
if (!adev->enable_mes_kiq && !ring->mqd_obj) {

View File

@ -557,8 +557,20 @@ static void amdgpu_mes_queue_init_mqd(struct amdgpu_device *adev,
mqd_prop.hqd_queue_priority = p->hqd_queue_priority;
mqd_prop.hqd_active = false;
if (p->queue_type == AMDGPU_RING_TYPE_GFX ||
p->queue_type == AMDGPU_RING_TYPE_COMPUTE) {
mutex_lock(&adev->srbm_mutex);
amdgpu_gfx_select_me_pipe_q(adev, p->ring->me, p->ring->pipe, 0, 0, 0);
}
mqd_mgr->init_mqd(adev, q->mqd_cpu_ptr, &mqd_prop);
if (p->queue_type == AMDGPU_RING_TYPE_GFX ||
p->queue_type == AMDGPU_RING_TYPE_COMPUTE) {
amdgpu_gfx_select_me_pipe_q(adev, 0, 0, 0, 0, 0);
mutex_unlock(&adev->srbm_mutex);
}
amdgpu_bo_unreserve(q->mqd_obj);
}
@ -994,9 +1006,13 @@ int amdgpu_mes_add_ring(struct amdgpu_device *adev, int gang_id,
switch (queue_type) {
case AMDGPU_RING_TYPE_GFX:
ring->funcs = adev->gfx.gfx_ring[0].funcs;
ring->me = adev->gfx.gfx_ring[0].me;
ring->pipe = adev->gfx.gfx_ring[0].pipe;
break;
case AMDGPU_RING_TYPE_COMPUTE:
ring->funcs = adev->gfx.compute_ring[0].funcs;
ring->me = adev->gfx.compute_ring[0].me;
ring->pipe = adev->gfx.compute_ring[0].pipe;
break;
case AMDGPU_RING_TYPE_SDMA:
ring->funcs = adev->sdma.instance[0].ring.funcs;

View File

@ -2120,6 +2120,21 @@ int amdgpu_psp_wait_for_bootloader(struct amdgpu_device *adev)
return ret;
}
int amdgpu_psp_query_boot_status(struct amdgpu_device *adev)
{
struct psp_context *psp = &adev->psp;
int ret = 0;
if (amdgpu_sriov_vf(adev) || (adev->flags & AMD_IS_APU))
return 0;
if (psp->funcs &&
psp->funcs->query_boot_status)
ret = psp->funcs->query_boot_status(psp);
return ret;
}
static int psp_hw_start(struct psp_context *psp)
{
struct amdgpu_device *adev = psp->adev;

View File

@ -134,6 +134,7 @@ struct psp_funcs {
int (*update_spirom)(struct psp_context *psp, uint64_t fw_pri_mc_addr);
int (*vbflash_stat)(struct psp_context *psp);
int (*fatal_error_recovery_quirk)(struct psp_context *psp);
int (*query_boot_status)(struct psp_context *psp);
};
struct ta_funcs {
@ -537,4 +538,6 @@ int is_psp_fw_valid(struct psp_bin_desc bin);
int amdgpu_psp_wait_for_bootloader(struct amdgpu_device *adev);
int amdgpu_psp_query_boot_status(struct amdgpu_device *adev);
#endif

View File

@ -1222,6 +1222,8 @@ int amdgpu_ras_reset_error_count(struct amdgpu_device *adev,
struct amdgpu_ras_block_object *block_obj = amdgpu_ras_get_ras_block(adev, block, 0);
struct amdgpu_ras *ras = amdgpu_ras_get_context(adev);
const struct amdgpu_mca_smu_funcs *mca_funcs = adev->mca.mca_funcs;
struct amdgpu_hive_info *hive;
int hive_ras_recovery = 0;
if (!block_obj || !block_obj->hw_ops) {
dev_dbg_once(adev->dev, "%s doesn't config RAS function\n",
@ -1229,15 +1231,22 @@ int amdgpu_ras_reset_error_count(struct amdgpu_device *adev,
return -EOPNOTSUPP;
}
/* skip ras error reset in gpu reset */
if ((amdgpu_in_reset(adev) || atomic_read(&ras->in_recovery)) &&
mca_funcs && mca_funcs->mca_set_debug_mode)
return -EOPNOTSUPP;
if (!amdgpu_ras_is_supported(adev, block) ||
!amdgpu_ras_get_mca_debug_mode(adev))
return -EOPNOTSUPP;
hive = amdgpu_get_xgmi_hive(adev);
if (hive) {
hive_ras_recovery = atomic_read(&hive->ras_recovery);
amdgpu_put_xgmi_hive(hive);
}
/* skip ras error reset in gpu reset */
if ((amdgpu_in_reset(adev) || atomic_read(&ras->in_recovery) ||
hive_ras_recovery) &&
mca_funcs && mca_funcs->mca_set_debug_mode)
return -EOPNOTSUPP;
if (block_obj->hw_ops->reset_ras_error_count)
block_obj->hw_ops->reset_ras_error_count(adev);

View File

@ -166,8 +166,12 @@ static int amdgpu_umc_do_page_retirement(struct amdgpu_device *adev,
}
}
if (reset)
if (reset) {
/* use mode-2 reset for poison consumption */
if (!entry)
con->gpu_reset_flags |= AMDGPU_RAS_GPU_RESET_MODE2_RESET;
amdgpu_ras_reset_gpu(adev);
}
}
kfree(err_data->err_addr);

View File

@ -1373,6 +1373,7 @@ int amdgpu_vm_clear_freed(struct amdgpu_device *adev,
*
* @adev: amdgpu_device pointer
* @vm: requested vm
* @ticket: optional reservation ticket used to reserve the VM
*
* Make sure all BOs which are moved are updated in the PTs.
*
@ -1382,11 +1383,12 @@ int amdgpu_vm_clear_freed(struct amdgpu_device *adev,
* PTs have to be reserved!
*/
int amdgpu_vm_handle_moved(struct amdgpu_device *adev,
struct amdgpu_vm *vm)
struct amdgpu_vm *vm,
struct ww_acquire_ctx *ticket)
{
struct amdgpu_bo_va *bo_va;
struct dma_resv *resv;
bool clear;
bool clear, unlock;
int r;
spin_lock(&vm->status_lock);
@ -1409,17 +1411,24 @@ int amdgpu_vm_handle_moved(struct amdgpu_device *adev,
spin_unlock(&vm->status_lock);
/* Try to reserve the BO to avoid clearing its ptes */
if (!adev->debug_vm && dma_resv_trylock(resv))
if (!adev->debug_vm && dma_resv_trylock(resv)) {
clear = false;
unlock = true;
/* The caller is already holding the reservation lock */
} else if (ticket && dma_resv_locking_ctx(resv) == ticket) {
clear = false;
unlock = false;
/* Somebody else is using the BO right now */
else
} else {
clear = true;
unlock = false;
}
r = amdgpu_vm_bo_update(adev, bo_va, clear);
if (r)
return r;
if (!clear)
if (unlock)
dma_resv_unlock(resv);
spin_lock(&vm->status_lock);
}

View File

@ -443,7 +443,8 @@ int amdgpu_vm_clear_freed(struct amdgpu_device *adev,
struct amdgpu_vm *vm,
struct dma_fence **fence);
int amdgpu_vm_handle_moved(struct amdgpu_device *adev,
struct amdgpu_vm *vm);
struct amdgpu_vm *vm,
struct ww_acquire_ctx *ticket);
void amdgpu_vm_bo_base_init(struct amdgpu_vm_bo_base *base,
struct amdgpu_vm *vm, struct amdgpu_bo *bo);
int amdgpu_vm_update_range(struct amdgpu_device *adev, struct amdgpu_vm *vm,

View File

@ -77,7 +77,16 @@ static inline bool amdgpu_is_vram_mgr_blocks_contiguous(struct list_head *head)
return true;
}
static inline u64 amdgpu_vram_mgr_blocks_size(struct list_head *head)
{
struct drm_buddy_block *block;
u64 size = 0;
list_for_each_entry(block, head, link)
size += amdgpu_vram_mgr_block_size(block);
return size;
}
/**
* DOC: mem_info_vram_total
@ -516,6 +525,8 @@ static int amdgpu_vram_mgr_new(struct ttm_resource_manager *man,
mutex_unlock(&mgr->lock);
vres->base.start = 0;
size = max_t(u64, amdgpu_vram_mgr_blocks_size(&vres->blocks),
vres->base.size);
list_for_each_entry(block, &vres->blocks, link) {
unsigned long start;
@ -523,8 +534,8 @@ static int amdgpu_vram_mgr_new(struct ttm_resource_manager *man,
amdgpu_vram_mgr_block_size(block);
start >>= PAGE_SHIFT;
if (start > PFN_UP(vres->base.size))
start -= PFN_UP(vres->base.size);
if (start > PFN_UP(size))
start -= PFN_UP(size);
else
start = 0;
vres->base.start = max(vres->base.start, start);

View File

@ -3498,6 +3498,8 @@ static void gfx_v10_0_ring_invalidate_tlbs(struct amdgpu_ring *ring,
static void gfx_v10_0_update_spm_vmid_internal(struct amdgpu_device *adev,
unsigned int vmid);
static int gfx_v10_0_set_powergating_state(void *handle,
enum amd_powergating_state state);
static void gfx10_kiq_set_resources(struct amdgpu_ring *kiq_ring, uint64_t queue_mask)
{
amdgpu_ring_write(kiq_ring, PACKET3(PACKET3_SET_RESOURCES, 6));
@ -6465,11 +6467,18 @@ static int gfx_v10_0_gfx_init_queue(struct amdgpu_ring *ring)
nv_grbm_select(adev, 0, 0, 0, 0);
mutex_unlock(&adev->srbm_mutex);
if (adev->gfx.me.mqd_backup[mqd_idx])
memcpy(adev->gfx.me.mqd_backup[mqd_idx], mqd, sizeof(*mqd));
memcpy_fromio(adev->gfx.me.mqd_backup[mqd_idx], mqd, sizeof(*mqd));
} else {
mutex_lock(&adev->srbm_mutex);
nv_grbm_select(adev, ring->me, ring->pipe, ring->queue, 0);
if (ring->doorbell_index == adev->doorbell_index.gfx_ring0 << 1)
gfx_v10_0_cp_gfx_set_doorbell(adev, ring);
nv_grbm_select(adev, 0, 0, 0, 0);
mutex_unlock(&adev->srbm_mutex);
/* restore mqd with the backup copy */
if (adev->gfx.me.mqd_backup[mqd_idx])
memcpy(mqd, adev->gfx.me.mqd_backup[mqd_idx], sizeof(*mqd));
memcpy_toio(mqd, adev->gfx.me.mqd_backup[mqd_idx], sizeof(*mqd));
/* reset the ring */
ring->wptr = 0;
*ring->wptr_cpu_addr = 0;
@ -6743,7 +6752,7 @@ static int gfx_v10_0_kiq_init_queue(struct amdgpu_ring *ring)
if (amdgpu_in_reset(adev)) { /* for GPU_RESET case */
/* reset MQD to a clean status */
if (adev->gfx.kiq[0].mqd_backup)
memcpy(mqd, adev->gfx.kiq[0].mqd_backup, sizeof(*mqd));
memcpy_toio(mqd, adev->gfx.kiq[0].mqd_backup, sizeof(*mqd));
/* reset ring buffer */
ring->wptr = 0;
@ -6766,7 +6775,7 @@ static int gfx_v10_0_kiq_init_queue(struct amdgpu_ring *ring)
mutex_unlock(&adev->srbm_mutex);
if (adev->gfx.kiq[0].mqd_backup)
memcpy(adev->gfx.kiq[0].mqd_backup, mqd, sizeof(*mqd));
memcpy_fromio(adev->gfx.kiq[0].mqd_backup, mqd, sizeof(*mqd));
}
return 0;
@ -6787,11 +6796,11 @@ static int gfx_v10_0_kcq_init_queue(struct amdgpu_ring *ring)
mutex_unlock(&adev->srbm_mutex);
if (adev->gfx.mec.mqd_backup[mqd_idx])
memcpy(adev->gfx.mec.mqd_backup[mqd_idx], mqd, sizeof(*mqd));
memcpy_fromio(adev->gfx.mec.mqd_backup[mqd_idx], mqd, sizeof(*mqd));
} else {
/* restore MQD to a clean status */
if (adev->gfx.mec.mqd_backup[mqd_idx])
memcpy(mqd, adev->gfx.mec.mqd_backup[mqd_idx], sizeof(*mqd));
memcpy_toio(mqd, adev->gfx.mec.mqd_backup[mqd_idx], sizeof(*mqd));
/* reset ring buffer */
ring->wptr = 0;
atomic64_set((atomic64_t *)ring->wptr_cpu_addr, 0);
@ -7172,6 +7181,13 @@ static int gfx_v10_0_hw_fini(void *handle)
amdgpu_irq_put(adev, &adev->gfx.priv_reg_irq, 0);
amdgpu_irq_put(adev, &adev->gfx.priv_inst_irq, 0);
/* WA added for Vangogh asic fixing the SMU suspend failure
* It needs to set power gating again during gfxoff control
* otherwise the gfxoff disallowing will be failed to set.
*/
if (amdgpu_ip_version(adev, GC_HWIP, 0) == IP_VERSION(10, 3, 1))
gfx_v10_0_set_powergating_state(handle, AMD_PG_STATE_UNGATE);
if (!adev->no_hw_access) {
if (amdgpu_async_gfx_ring) {
if (amdgpu_gfx_disable_kgq(adev, 0))

View File

@ -155,6 +155,7 @@ static void gfx11_kiq_set_resources(struct amdgpu_ring *kiq_ring, uint64_t queue
{
amdgpu_ring_write(kiq_ring, PACKET3(PACKET3_SET_RESOURCES, 6));
amdgpu_ring_write(kiq_ring, PACKET3_SET_RESOURCES_VMID_MASK(0) |
PACKET3_SET_RESOURCES_UNMAP_LATENTY(0xa) | /* unmap_latency: 0xa (~ 1s) */
PACKET3_SET_RESOURCES_QUEUE_TYPE(0)); /* vmid_mask:0 queue_type:0 (KIQ) */
amdgpu_ring_write(kiq_ring, lower_32_bits(queue_mask)); /* queue mask lo */
amdgpu_ring_write(kiq_ring, upper_32_bits(queue_mask)); /* queue mask hi */
@ -3714,11 +3715,11 @@ static int gfx_v11_0_gfx_init_queue(struct amdgpu_ring *ring)
soc21_grbm_select(adev, 0, 0, 0, 0);
mutex_unlock(&adev->srbm_mutex);
if (adev->gfx.me.mqd_backup[mqd_idx])
memcpy(adev->gfx.me.mqd_backup[mqd_idx], mqd, sizeof(*mqd));
memcpy_fromio(adev->gfx.me.mqd_backup[mqd_idx], mqd, sizeof(*mqd));
} else {
/* restore mqd with the backup copy */
if (adev->gfx.me.mqd_backup[mqd_idx])
memcpy(mqd, adev->gfx.me.mqd_backup[mqd_idx], sizeof(*mqd));
memcpy_toio(mqd, adev->gfx.me.mqd_backup[mqd_idx], sizeof(*mqd));
/* reset the ring */
ring->wptr = 0;
*ring->wptr_cpu_addr = 0;
@ -4007,7 +4008,7 @@ static int gfx_v11_0_kiq_init_queue(struct amdgpu_ring *ring)
if (amdgpu_in_reset(adev)) { /* for GPU_RESET case */
/* reset MQD to a clean status */
if (adev->gfx.kiq[0].mqd_backup)
memcpy(mqd, adev->gfx.kiq[0].mqd_backup, sizeof(*mqd));
memcpy_toio(mqd, adev->gfx.kiq[0].mqd_backup, sizeof(*mqd));
/* reset ring buffer */
ring->wptr = 0;
@ -4030,7 +4031,7 @@ static int gfx_v11_0_kiq_init_queue(struct amdgpu_ring *ring)
mutex_unlock(&adev->srbm_mutex);
if (adev->gfx.kiq[0].mqd_backup)
memcpy(adev->gfx.kiq[0].mqd_backup, mqd, sizeof(*mqd));
memcpy_fromio(adev->gfx.kiq[0].mqd_backup, mqd, sizeof(*mqd));
}
return 0;
@ -4051,11 +4052,11 @@ static int gfx_v11_0_kcq_init_queue(struct amdgpu_ring *ring)
mutex_unlock(&adev->srbm_mutex);
if (adev->gfx.mec.mqd_backup[mqd_idx])
memcpy(adev->gfx.mec.mqd_backup[mqd_idx], mqd, sizeof(*mqd));
memcpy_fromio(adev->gfx.mec.mqd_backup[mqd_idx], mqd, sizeof(*mqd));
} else {
/* restore MQD to a clean status */
if (adev->gfx.mec.mqd_backup[mqd_idx])
memcpy(mqd, adev->gfx.mec.mqd_backup[mqd_idx], sizeof(*mqd));
memcpy_toio(mqd, adev->gfx.mec.mqd_backup[mqd_idx], sizeof(*mqd));
/* reset ring buffer */
ring->wptr = 0;
atomic64_set((atomic64_t *)ring->wptr_cpu_addr, 0);

View File

@ -28,6 +28,7 @@
#include "nbio/nbio_2_3_offset.h"
#include "nbio/nbio_2_3_sh_mask.h"
#include <uapi/linux/kfd_ioctl.h>
#include <linux/device.h>
#include <linux/pci.h>
#define smnPCIE_CONFIG_CNTL 0x11180044
@ -361,7 +362,7 @@ static void nbio_v2_3_enable_aspm(struct amdgpu_device *adev,
data |= NAVI10_PCIE__LC_L0S_INACTIVITY_DEFAULT << PCIE_LC_CNTL__LC_L0S_INACTIVITY__SHIFT;
if (pci_is_thunderbolt_attached(adev->pdev))
if (dev_is_removable(&adev->pdev->dev))
data |= NAVI10_PCIE__LC_L1_INACTIVITY_TBT_DEFAULT << PCIE_LC_CNTL__LC_L1_INACTIVITY__SHIFT;
else
data |= NAVI10_PCIE__LC_L1_INACTIVITY_DEFAULT << PCIE_LC_CNTL__LC_L1_INACTIVITY__SHIFT;
@ -480,7 +481,7 @@ static void nbio_v2_3_program_aspm(struct amdgpu_device *adev)
def = data = RREG32_PCIE(smnPCIE_LC_CNTL);
data |= NAVI10_PCIE__LC_L0S_INACTIVITY_DEFAULT << PCIE_LC_CNTL__LC_L0S_INACTIVITY__SHIFT;
if (pci_is_thunderbolt_attached(adev->pdev))
if (dev_is_removable(&adev->pdev->dev))
data |= NAVI10_PCIE__LC_L1_INACTIVITY_TBT_DEFAULT << PCIE_LC_CNTL__LC_L1_INACTIVITY__SHIFT;
else
data |= NAVI10_PCIE__LC_L1_INACTIVITY_DEFAULT << PCIE_LC_CNTL__LC_L1_INACTIVITY__SHIFT;

View File

@ -759,6 +759,83 @@ static int psp_v13_0_fatal_error_recovery_quirk(struct psp_context *psp)
return 0;
}
static void psp_v13_0_boot_error_reporting(struct amdgpu_device *adev,
uint32_t inst,
uint32_t boot_error)
{
uint32_t socket_id;
uint32_t aid_id;
uint32_t hbm_id;
uint32_t reg_data;
socket_id = REG_GET_FIELD(boot_error, MP0_SMN_C2PMSG_126, SOCKET_ID);
aid_id = REG_GET_FIELD(boot_error, MP0_SMN_C2PMSG_126, AID_ID);
hbm_id = REG_GET_FIELD(boot_error, MP0_SMN_C2PMSG_126, HBM_ID);
reg_data = RREG32_SOC15(MP0, inst, regMP0_SMN_C2PMSG_109);
dev_info(adev->dev, "socket: %d, aid: %d, firmware boot failed, fw status is 0x%x\n",
socket_id, aid_id, reg_data);
if (REG_GET_FIELD(boot_error, MP0_SMN_C2PMSG_126, GPU_ERR_MEM_TRAINING))
dev_info(adev->dev, "socket: %d, aid: %d, hbm: %d, memory training failed\n",
socket_id, aid_id, hbm_id);
if (REG_GET_FIELD(boot_error, MP0_SMN_C2PMSG_126, GPU_ERR_FW_LOAD))
dev_info(adev->dev, "socket: %d, aid: %d, firmware load failed at boot time\n",
socket_id, aid_id);
if (REG_GET_FIELD(boot_error, MP0_SMN_C2PMSG_126, GPU_ERR_WAFL_LINK_TRAINING))
dev_info(adev->dev, "socket: %d, aid: %d, wafl link training failed\n",
socket_id, aid_id);
if (REG_GET_FIELD(boot_error, MP0_SMN_C2PMSG_126, GPU_ERR_XGMI_LINK_TRAINING))
dev_info(adev->dev, "socket: %d, aid: %d, xgmi link training failed\n",
socket_id, aid_id);
if (REG_GET_FIELD(boot_error, MP0_SMN_C2PMSG_126, GPU_ERR_USR_CP_LINK_TRAINING))
dev_info(adev->dev, "socket: %d, aid: %d, usr cp link training failed\n",
socket_id, aid_id);
if (REG_GET_FIELD(boot_error, MP0_SMN_C2PMSG_126, GPU_ERR_USR_DP_LINK_TRAINING))
dev_info(adev->dev, "socket: %d, aid: %d, usr dp link training failed\n",
socket_id, aid_id);
if (REG_GET_FIELD(boot_error, MP0_SMN_C2PMSG_126, GPU_ERR_HBM_MEM_TEST))
dev_info(adev->dev, "socket: %d, aid: %d, hbm: %d, hbm memory test failed\n",
socket_id, aid_id, hbm_id);
if (REG_GET_FIELD(boot_error, MP0_SMN_C2PMSG_126, GPU_ERR_HBM_BIST_TEST))
dev_info(adev->dev, "socket: %d, aid: %d, hbm: %d, hbm bist test failed\n",
socket_id, aid_id, hbm_id);
}
static int psp_v13_0_query_boot_status(struct psp_context *psp)
{
struct amdgpu_device *adev = psp->adev;
int inst_mask = adev->aid_mask;
uint32_t reg_data;
uint32_t i;
int ret = 0;
if (amdgpu_ip_version(adev, MP0_HWIP, 0) != IP_VERSION(13, 0, 6))
return 0;
if (RREG32_SOC15(MP0, 0, regMP0_SMN_C2PMSG_59) < 0x00a10007)
return 0;
for_each_inst(i, inst_mask) {
reg_data = RREG32_SOC15(MP0, i, regMP0_SMN_C2PMSG_126);
if (!REG_GET_FIELD(reg_data, MP0_SMN_C2PMSG_126, BOOT_STATUS)) {
psp_v13_0_boot_error_reporting(adev, i, reg_data);
ret = -EINVAL;
break;
}
}
return ret;
}
static const struct psp_funcs psp_v13_0_funcs = {
.init_microcode = psp_v13_0_init_microcode,
.wait_for_bootloader = psp_v13_0_wait_for_bootloader_steady_state,
@ -781,6 +858,7 @@ static const struct psp_funcs psp_v13_0_funcs = {
.update_spirom = psp_v13_0_update_spirom,
.vbflash_stat = psp_v13_0_vbflash_status,
.fatal_error_recovery_quirk = psp_v13_0_fatal_error_recovery_quirk,
.query_boot_status = psp_v13_0_query_boot_status,
};
void psp_v13_0_set_psp_funcs(struct psp_context *psp)

View File

@ -91,8 +91,7 @@ static void umc_v12_0_reset_error_count(struct amdgpu_device *adev)
static bool umc_v12_0_is_uncorrectable_error(uint64_t mc_umc_status)
{
return ((REG_GET_FIELD(mc_umc_status, MCA_UMC_UMC0_MCUMC_STATUST0, Val) == 1) &&
(REG_GET_FIELD(mc_umc_status, MCA_UMC_UMC0_MCUMC_STATUST0, Deferred) == 1 ||
REG_GET_FIELD(mc_umc_status, MCA_UMC_UMC0_MCUMC_STATUST0, PCC) == 1 ||
(REG_GET_FIELD(mc_umc_status, MCA_UMC_UMC0_MCUMC_STATUST0, PCC) == 1 ||
REG_GET_FIELD(mc_umc_status, MCA_UMC_UMC0_MCUMC_STATUST0, UC) == 1 ||
REG_GET_FIELD(mc_umc_status, MCA_UMC_UMC0_MCUMC_STATUST0, TCC) == 1));
}

View File

@ -1404,6 +1404,66 @@ static int kfd_fill_gpu_cache_info_from_gfx_config(struct kfd_dev *kdev,
return i;
}
static int kfd_fill_gpu_cache_info_from_gfx_config_v2(struct kfd_dev *kdev,
struct kfd_gpu_cache_info *pcache_info)
{
struct amdgpu_device *adev = kdev->adev;
int i = 0;
/* TCP L1 Cache per CU */
if (adev->gfx.config.gc_tcp_size_per_cu) {
pcache_info[i].cache_size = adev->gfx.config.gc_tcp_size_per_cu;
pcache_info[i].cache_level = 1;
pcache_info[i].flags = (CRAT_CACHE_FLAGS_ENABLED |
CRAT_CACHE_FLAGS_DATA_CACHE |
CRAT_CACHE_FLAGS_SIMD_CACHE);
pcache_info[i].num_cu_shared = 1;
i++;
}
/* Scalar L1 Instruction Cache per SQC */
if (adev->gfx.config.gc_l1_instruction_cache_size_per_sqc) {
pcache_info[i].cache_size =
adev->gfx.config.gc_l1_instruction_cache_size_per_sqc;
pcache_info[i].cache_level = 1;
pcache_info[i].flags = (CRAT_CACHE_FLAGS_ENABLED |
CRAT_CACHE_FLAGS_INST_CACHE |
CRAT_CACHE_FLAGS_SIMD_CACHE);
pcache_info[i].num_cu_shared = adev->gfx.config.gc_num_cu_per_sqc;
i++;
}
/* Scalar L1 Data Cache per SQC */
if (adev->gfx.config.gc_l1_data_cache_size_per_sqc) {
pcache_info[i].cache_size = adev->gfx.config.gc_l1_data_cache_size_per_sqc;
pcache_info[i].cache_level = 1;
pcache_info[i].flags = (CRAT_CACHE_FLAGS_ENABLED |
CRAT_CACHE_FLAGS_DATA_CACHE |
CRAT_CACHE_FLAGS_SIMD_CACHE);
pcache_info[i].num_cu_shared = adev->gfx.config.gc_num_cu_per_sqc;
i++;
}
/* L2 Data Cache per GPU (Total Tex Cache) */
if (adev->gfx.config.gc_tcc_size) {
pcache_info[i].cache_size = adev->gfx.config.gc_tcc_size;
pcache_info[i].cache_level = 2;
pcache_info[i].flags = (CRAT_CACHE_FLAGS_ENABLED |
CRAT_CACHE_FLAGS_DATA_CACHE |
CRAT_CACHE_FLAGS_SIMD_CACHE);
pcache_info[i].num_cu_shared = adev->gfx.config.max_cu_per_sh;
i++;
}
/* L3 Data Cache per GPU */
if (adev->gmc.mall_size) {
pcache_info[i].cache_size = adev->gmc.mall_size / 1024;
pcache_info[i].cache_level = 3;
pcache_info[i].flags = (CRAT_CACHE_FLAGS_ENABLED |
CRAT_CACHE_FLAGS_DATA_CACHE |
CRAT_CACHE_FLAGS_SIMD_CACHE);
pcache_info[i].num_cu_shared = adev->gfx.config.max_cu_per_sh;
i++;
}
return i;
}
int kfd_get_gpu_cache_info(struct kfd_node *kdev, struct kfd_gpu_cache_info **pcache_info)
{
int num_of_cache_types = 0;
@ -1461,10 +1521,14 @@ int kfd_get_gpu_cache_info(struct kfd_node *kdev, struct kfd_gpu_cache_info **pc
num_of_cache_types = ARRAY_SIZE(vega20_cache_info);
break;
case IP_VERSION(9, 4, 2):
case IP_VERSION(9, 4, 3):
*pcache_info = aldebaran_cache_info;
num_of_cache_types = ARRAY_SIZE(aldebaran_cache_info);
break;
case IP_VERSION(9, 4, 3):
num_of_cache_types =
kfd_fill_gpu_cache_info_from_gfx_config_v2(kdev->kfd,
*pcache_info);
break;
case IP_VERSION(9, 1, 0):
case IP_VERSION(9, 2, 2):
*pcache_info = raven_cache_info;

View File

@ -1602,10 +1602,13 @@ static int fill_in_l2_l3_pcache(struct kfd_cache_properties **props_ext,
unsigned int cu_sibling_map_mask;
int first_active_cu;
int i, j, k, xcc, start, end;
int num_xcc = NUM_XCC(knode->xcc_mask);
struct kfd_cache_properties *pcache = NULL;
enum amdgpu_memory_partition mode;
struct amdgpu_device *adev = knode->adev;
start = ffs(knode->xcc_mask) - 1;
end = start + NUM_XCC(knode->xcc_mask);
end = start + num_xcc;
cu_sibling_map_mask = cu_info->bitmap[start][0][0];
cu_sibling_map_mask &=
((1 << pcache_info[cache_type].num_cu_shared) - 1);
@ -1624,7 +1627,18 @@ static int fill_in_l2_l3_pcache(struct kfd_cache_properties **props_ext,
pcache->processor_id_low = cu_processor_id
+ (first_active_cu - 1);
pcache->cache_level = pcache_info[cache_type].cache_level;
pcache->cache_size = pcache_info[cache_type].cache_size;
if (KFD_GC_VERSION(knode) == IP_VERSION(9, 4, 3))
mode = adev->gmc.gmc_funcs->query_mem_partition_mode(adev);
else
mode = UNKNOWN_MEMORY_PARTITION_MODE;
if (pcache->cache_level == 2)
pcache->cache_size = pcache_info[cache_type].cache_size * num_xcc;
else if (mode)
pcache->cache_size = pcache_info[cache_type].cache_size / mode;
else
pcache->cache_size = pcache_info[cache_type].cache_size;
if (pcache_info[cache_type].flags & CRAT_CACHE_FLAGS_DATA_CACHE)
pcache->cache_type |= HSA_CACHE_TYPE_DATA;

View File

@ -4348,7 +4348,6 @@ static bool full_update_required(struct dc *dc,
srf_updates[i].in_transfer_func ||
srf_updates[i].func_shaper ||
srf_updates[i].lut3d_func ||
srf_updates[i].blend_tf ||
srf_updates[i].surface->force_full_update ||
(srf_updates[i].flip_addr &&
srf_updates[i].flip_addr->address.tmz_surface != srf_updates[i].surface->address.tmz_surface) ||

View File

@ -533,7 +533,7 @@ uint32_t dc_stream_get_vblank_counter(const struct dc_stream_state *stream)
for (i = 0; i < MAX_PIPES; i++) {
struct timing_generator *tg = res_ctx->pipe_ctx[i].stream_res.tg;
if (res_ctx->pipe_ctx[i].stream != stream)
if (res_ctx->pipe_ctx[i].stream != stream || !tg)
continue;
return tg->funcs->get_frame_count(tg);
@ -592,7 +592,7 @@ bool dc_stream_get_scanoutpos(const struct dc_stream_state *stream,
for (i = 0; i < MAX_PIPES; i++) {
struct timing_generator *tg = res_ctx->pipe_ctx[i].stream_res.tg;
if (res_ctx->pipe_ctx[i].stream != stream)
if (res_ctx->pipe_ctx[i].stream != stream || !tg)
continue;
tg->funcs->get_scanoutpos(tg,

View File

@ -613,16 +613,19 @@ static void dpp3_program_blnd_pwl(
REG_SET(CM_BLNDGAM_LUT_DATA, 0, CM_BLNDGAM_LUT_DATA, rgb[i].red_reg);
REG_SET(CM_BLNDGAM_LUT_DATA, 0, CM_BLNDGAM_LUT_DATA, last_base_value_red);
} else {
REG_SET(CM_BLNDGAM_LUT_INDEX, 0, CM_BLNDGAM_LUT_INDEX, 0);
REG_UPDATE(CM_BLNDGAM_LUT_CONTROL, CM_BLNDGAM_LUT_WRITE_COLOR_MASK, 4);
for (i = 0 ; i < num; i++)
REG_SET(CM_BLNDGAM_LUT_DATA, 0, CM_BLNDGAM_LUT_DATA, rgb[i].red_reg);
REG_SET(CM_BLNDGAM_LUT_DATA, 0, CM_BLNDGAM_LUT_DATA, last_base_value_red);
REG_SET(CM_BLNDGAM_LUT_INDEX, 0, CM_BLNDGAM_LUT_INDEX, 0);
REG_UPDATE(CM_BLNDGAM_LUT_CONTROL, CM_BLNDGAM_LUT_WRITE_COLOR_MASK, 2);
for (i = 0 ; i < num; i++)
REG_SET(CM_BLNDGAM_LUT_DATA, 0, CM_BLNDGAM_LUT_DATA, rgb[i].green_reg);
REG_SET(CM_BLNDGAM_LUT_DATA, 0, CM_BLNDGAM_LUT_DATA, last_base_value_green);
REG_SET(CM_BLNDGAM_LUT_INDEX, 0, CM_BLNDGAM_LUT_INDEX, 0);
REG_UPDATE(CM_BLNDGAM_LUT_CONTROL, CM_BLNDGAM_LUT_WRITE_COLOR_MASK, 1);
for (i = 0 ; i < num; i++)
REG_SET(CM_BLNDGAM_LUT_DATA, 0, CM_BLNDGAM_LUT_DATA, rgb[i].blue_reg);

View File

@ -316,7 +316,7 @@ bool hubp3_program_surface_flip_and_addr(
return true;
}
static void hubp3_program_tiling(
void hubp3_program_tiling(
struct dcn20_hubp *hubp2,
const union dc_tiling_info *info,
const enum surface_pixel_format pixel_format)

View File

@ -278,6 +278,11 @@ void hubp3_setup(
struct _vcs_dpi_display_rq_regs_st *rq_regs,
struct _vcs_dpi_display_pipe_dest_params_st *pipe_dest);
void hubp3_program_tiling(
struct dcn20_hubp *hubp2,
const union dc_tiling_info *info,
const enum surface_pixel_format pixel_format);
void hubp3_dcc_control(struct hubp *hubp, bool enable,
enum hubp_ind_block_size blk_size);

View File

@ -237,16 +237,19 @@ void mpc32_program_post1dlut_pwl(
REG_SET(MPCC_MCM_1DLUT_LUT_DATA[mpcc_id], 0, MPCC_MCM_1DLUT_LUT_DATA, rgb[i].red_reg);
REG_SET(MPCC_MCM_1DLUT_LUT_DATA[mpcc_id], 0, MPCC_MCM_1DLUT_LUT_DATA, last_base_value_red);
} else {
REG_SET(MPCC_MCM_1DLUT_LUT_INDEX[mpcc_id], 0, MPCC_MCM_1DLUT_LUT_INDEX, 0);
REG_UPDATE(MPCC_MCM_1DLUT_LUT_CONTROL[mpcc_id], MPCC_MCM_1DLUT_LUT_WRITE_COLOR_MASK, 4);
for (i = 0 ; i < num; i++)
REG_SET(MPCC_MCM_1DLUT_LUT_DATA[mpcc_id], 0, MPCC_MCM_1DLUT_LUT_DATA, rgb[i].red_reg);
REG_SET(MPCC_MCM_1DLUT_LUT_DATA[mpcc_id], 0, MPCC_MCM_1DLUT_LUT_DATA, last_base_value_red);
REG_SET(MPCC_MCM_1DLUT_LUT_INDEX[mpcc_id], 0, MPCC_MCM_1DLUT_LUT_INDEX, 0);
REG_UPDATE(MPCC_MCM_1DLUT_LUT_CONTROL[mpcc_id], MPCC_MCM_1DLUT_LUT_WRITE_COLOR_MASK, 2);
for (i = 0 ; i < num; i++)
REG_SET(MPCC_MCM_1DLUT_LUT_DATA[mpcc_id], 0, MPCC_MCM_1DLUT_LUT_DATA, rgb[i].green_reg);
REG_SET(MPCC_MCM_1DLUT_LUT_DATA[mpcc_id], 0, MPCC_MCM_1DLUT_LUT_DATA, last_base_value_green);
REG_SET(MPCC_MCM_1DLUT_LUT_INDEX[mpcc_id], 0, MPCC_MCM_1DLUT_LUT_INDEX, 0);
REG_UPDATE(MPCC_MCM_1DLUT_LUT_CONTROL[mpcc_id], MPCC_MCM_1DLUT_LUT_WRITE_COLOR_MASK, 1);
for (i = 0 ; i < num; i++)
REG_SET(MPCC_MCM_1DLUT_LUT_DATA[mpcc_id], 0, MPCC_MCM_1DLUT_LUT_DATA, rgb[i].blue_reg);

View File

@ -53,11 +53,146 @@ static void hubp35_init(struct hubp *hubp)
/*do nothing for now for dcn3.5 or later*/
}
void hubp35_program_pixel_format(
struct hubp *hubp,
enum surface_pixel_format format)
{
struct dcn20_hubp *hubp2 = TO_DCN20_HUBP(hubp);
uint32_t green_bar = 1;
uint32_t red_bar = 3;
uint32_t blue_bar = 2;
/* swap for ABGR format */
if (format == SURFACE_PIXEL_FORMAT_GRPH_ABGR8888
|| format == SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010
|| format == SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010_XR_BIAS
|| format == SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616
|| format == SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616F) {
red_bar = 2;
blue_bar = 3;
}
REG_UPDATE_3(HUBPRET_CONTROL,
CROSSBAR_SRC_Y_G, green_bar,
CROSSBAR_SRC_CB_B, blue_bar,
CROSSBAR_SRC_CR_R, red_bar);
/* Mapping is same as ipp programming (cnvc) */
switch (format) {
case SURFACE_PIXEL_FORMAT_GRPH_ARGB1555:
REG_UPDATE(DCSURF_SURFACE_CONFIG,
SURFACE_PIXEL_FORMAT, 1);
break;
case SURFACE_PIXEL_FORMAT_GRPH_RGB565:
REG_UPDATE(DCSURF_SURFACE_CONFIG,
SURFACE_PIXEL_FORMAT, 3);
break;
case SURFACE_PIXEL_FORMAT_GRPH_ARGB8888:
case SURFACE_PIXEL_FORMAT_GRPH_ABGR8888:
REG_UPDATE(DCSURF_SURFACE_CONFIG,
SURFACE_PIXEL_FORMAT, 8);
break;
case SURFACE_PIXEL_FORMAT_GRPH_ARGB2101010:
case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010:
case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010_XR_BIAS:
REG_UPDATE(DCSURF_SURFACE_CONFIG,
SURFACE_PIXEL_FORMAT, 10);
break;
case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616:
case SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616: /* we use crossbar already */
REG_UPDATE(DCSURF_SURFACE_CONFIG,
SURFACE_PIXEL_FORMAT, 26); /* ARGB16161616_UNORM */
break;
case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616F:
case SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616F:/*we use crossbar already*/
REG_UPDATE(DCSURF_SURFACE_CONFIG,
SURFACE_PIXEL_FORMAT, 24);
break;
case SURFACE_PIXEL_FORMAT_VIDEO_420_YCbCr:
REG_UPDATE(DCSURF_SURFACE_CONFIG,
SURFACE_PIXEL_FORMAT, 65);
break;
case SURFACE_PIXEL_FORMAT_VIDEO_420_YCrCb:
REG_UPDATE(DCSURF_SURFACE_CONFIG,
SURFACE_PIXEL_FORMAT, 64);
break;
case SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCbCr:
REG_UPDATE(DCSURF_SURFACE_CONFIG,
SURFACE_PIXEL_FORMAT, 67);
break;
case SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCrCb:
REG_UPDATE(DCSURF_SURFACE_CONFIG,
SURFACE_PIXEL_FORMAT, 66);
break;
case SURFACE_PIXEL_FORMAT_VIDEO_AYCrCb8888:
REG_UPDATE(DCSURF_SURFACE_CONFIG,
SURFACE_PIXEL_FORMAT, 12);
break;
case SURFACE_PIXEL_FORMAT_GRPH_RGB111110_FIX:
REG_UPDATE(DCSURF_SURFACE_CONFIG,
SURFACE_PIXEL_FORMAT, 112);
break;
case SURFACE_PIXEL_FORMAT_GRPH_BGR101111_FIX:
REG_UPDATE(DCSURF_SURFACE_CONFIG,
SURFACE_PIXEL_FORMAT, 113);
break;
case SURFACE_PIXEL_FORMAT_VIDEO_ACrYCb2101010:
REG_UPDATE(DCSURF_SURFACE_CONFIG,
SURFACE_PIXEL_FORMAT, 114);
break;
case SURFACE_PIXEL_FORMAT_GRPH_RGB111110_FLOAT:
REG_UPDATE(DCSURF_SURFACE_CONFIG,
SURFACE_PIXEL_FORMAT, 118);
break;
case SURFACE_PIXEL_FORMAT_GRPH_BGR101111_FLOAT:
REG_UPDATE(DCSURF_SURFACE_CONFIG,
SURFACE_PIXEL_FORMAT, 119);
break;
case SURFACE_PIXEL_FORMAT_GRPH_RGBE:
REG_UPDATE_2(DCSURF_SURFACE_CONFIG,
SURFACE_PIXEL_FORMAT, 116,
ALPHA_PLANE_EN, 0);
break;
case SURFACE_PIXEL_FORMAT_GRPH_RGBE_ALPHA:
REG_UPDATE_2(DCSURF_SURFACE_CONFIG,
SURFACE_PIXEL_FORMAT, 116,
ALPHA_PLANE_EN, 1);
break;
default:
BREAK_TO_DEBUGGER();
break;
}
/* don't see the need of program the xbar in DCN 1.0 */
}
void hubp35_program_surface_config(
struct hubp *hubp,
enum surface_pixel_format format,
union dc_tiling_info *tiling_info,
struct plane_size *plane_size,
enum dc_rotation_angle rotation,
struct dc_plane_dcc_param *dcc,
bool horizontal_mirror,
unsigned int compat_level)
{
struct dcn20_hubp *hubp2 = TO_DCN20_HUBP(hubp);
hubp3_dcc_control_sienna_cichlid(hubp, dcc);
hubp3_program_tiling(hubp2, tiling_info, format);
hubp2_program_size(hubp, format, plane_size, dcc);
hubp2_program_rotation(hubp, rotation, horizontal_mirror);
hubp35_program_pixel_format(hubp, format);
}
struct hubp_funcs dcn35_hubp_funcs = {
.hubp_enable_tripleBuffer = hubp2_enable_triplebuffer,
.hubp_is_triplebuffer_enabled = hubp2_is_triplebuffer_enabled,
.hubp_program_surface_flip_and_addr = hubp3_program_surface_flip_and_addr,
.hubp_program_surface_config = hubp3_program_surface_config,
.hubp_program_surface_config = hubp35_program_surface_config,
.hubp_is_flip_pending = hubp2_is_flip_pending,
.hubp_setup = hubp3_setup,
.hubp_setup_interdependent = hubp2_setup_interdependent,

View File

@ -58,4 +58,18 @@ bool hubp35_construct(
void hubp35_set_fgcg(struct hubp *hubp, bool enable);
void hubp35_program_pixel_format(
struct hubp *hubp,
enum surface_pixel_format format);
void hubp35_program_surface_config(
struct hubp *hubp,
enum surface_pixel_format format,
union dc_tiling_info *tiling_info,
struct plane_size *plane_size,
enum dc_rotation_angle rotation,
struct dc_plane_dcc_param *dcc,
bool horizontal_mirror,
unsigned int compat_level);
#endif /* __DC_HUBP_DCN35_H__ */

View File

@ -60,8 +60,12 @@ endif
endif
ifneq ($(CONFIG_FRAME_WARN),0)
ifeq ($(filter y,$(CONFIG_KASAN)$(CONFIG_KCSAN)),y)
frame_warn_flag := -Wframe-larger-than=3072
else
frame_warn_flag := -Wframe-larger-than=2048
endif
endif
CFLAGS_$(AMDDALPATH)/dc/dml2/display_mode_core.o := $(dml2_ccflags) $(frame_warn_flag)
CFLAGS_$(AMDDALPATH)/dc/dml2/display_mode_util.o := $(dml2_ccflags)

View File

@ -242,6 +242,34 @@
//MP0_SMN_C2PMSG_103
#define MP0_SMN_C2PMSG_103__CONTENT__SHIFT 0x0
#define MP0_SMN_C2PMSG_103__CONTENT_MASK 0xFFFFFFFFL
//MP0_SMN_C2PMSG_109
#define MP0_SMN_C2PMSG_109__CONTENT__SHIFT 0x0
#define MP0_SMN_C2PMSG_109__CONTENT_MASK 0xFFFFFFFFL
//MP0_SMN_C2PMSG_126
#define MP0_SMN_C2PMSG_126__GPU_ERR_MEM_TRAINING__SHIFT 0x0
#define MP0_SMN_C2PMSG_126__GPU_ERR_FW_LOAD__SHIFT 0x1
#define MP0_SMN_C2PMSG_126__GPU_ERR_WAFL_LINK_TRAINING__SHIFT 0x2
#define MP0_SMN_C2PMSG_126__GPU_ERR_XGMI_LINK_TRAINING__SHIFT 0x3
#define MP0_SMN_C2PMSG_126__GPU_ERR_USR_CP_LINK_TRAINING__SHIFT 0x4
#define MP0_SMN_C2PMSG_126__GPU_ERR_USR_DP_LINK_TRAINING__SHIFT 0x5
#define MP0_SMN_C2PMSG_126__GPU_ERR_HBM_MEM_TEST__SHIFT 0x6
#define MP0_SMN_C2PMSG_126__GPU_ERR_HBM_BIST_TEST__SHIFT 0x7
#define MP0_SMN_C2PMSG_126__SOCKET_ID__SHIFT 0x8
#define MP0_SMN_C2PMSG_126__AID_ID__SHIFT 0xb
#define MP0_SMN_C2PMSG_126__HBM_ID__SHIFT 0xd
#define MP0_SMN_C2PMSG_126__BOOT_STATUS__SHIFT 0x1f
#define MP0_SMN_C2PMSG_126__GPU_ERR_MEM_TRAINING_MASK 0x00000001L
#define MP0_SMN_C2PMSG_126__GPU_ERR_FW_LOAD_MASK 0x00000002L
#define MP0_SMN_C2PMSG_126__GPU_ERR_WAFL_LINK_TRAINING_MASK 0x00000004L
#define MP0_SMN_C2PMSG_126__GPU_ERR_XGMI_LINK_TRAINING_MASK 0x00000008L
#define MP0_SMN_C2PMSG_126__GPU_ERR_USR_CP_LINK_TRAINING_MASK 0x00000010L
#define MP0_SMN_C2PMSG_126__GPU_ERR_USR_DP_LINK_TRAINING_MASK 0x00000020L
#define MP0_SMN_C2PMSG_126__GPU_ERR_HBM_MEM_TEST_MASK 0x00000040L
#define MP0_SMN_C2PMSG_126__GPU_ERR_HBM_BIST_TEST_MASK 0x00000080L
#define MP0_SMN_C2PMSG_126__SOCKET_ID_MASK 0x00000700L
#define MP0_SMN_C2PMSG_126__AID_ID_MASK 0x00001800L
#define MP0_SMN_C2PMSG_126__HBM_ID_MASK 0x00002000L
#define MP0_SMN_C2PMSG_126__BOOT_STATUS_MASK 0x80000000L
//MP0_SMN_IH_CREDIT
#define MP0_SMN_IH_CREDIT__CREDIT_VALUE__SHIFT 0x0
#define MP0_SMN_IH_CREDIT__CLIENT_ID__SHIFT 0x10

View File

@ -1080,33 +1080,35 @@ struct gpu_metrics_v3_0 {
uint16_t average_ipu_activity[8];
/* time filtered per-core C0 residency % [0-100]*/
uint16_t average_core_c0_activity[16];
/* time filtered DRAM read bandwidth [GB/sec] */
/* time filtered DRAM read bandwidth [MB/sec] */
uint16_t average_dram_reads;
/* time filtered DRAM write bandwidth [GB/sec] */
/* time filtered DRAM write bandwidth [MB/sec] */
uint16_t average_dram_writes;
/* Driver attached timestamp (in ns) */
uint64_t system_clock_counter;
/* Power/Energy */
/* average dGPU + APU power on A + A platform */
/* time filtered power used for PPT/STAPM [APU+dGPU] [mW] */
uint32_t average_socket_power;
/* average IPU power [W] */
/* time filtered IPU power [mW] */
uint16_t average_ipu_power;
/* average APU power [W] */
/* time filtered APU power [mW] */
uint32_t average_apu_power;
/* average dGPU power [W] */
/* time filtered GFX power [mW] */
uint32_t average_gfx_power;
/* time filtered dGPU power [mW] */
uint32_t average_dgpu_power;
/* sum of core power across all cores in the socket [W] */
uint32_t average_core_power;
/* calculated core power [W] */
uint16_t core_power[16];
/* maximum IRM defined STAPM power limit [W] */
/* time filtered sum of core power across all cores in the socket [mW] */
uint32_t average_all_core_power;
/* calculated core power [mW] */
uint16_t average_core_power[16];
/* maximum IRM defined STAPM power limit [mW] */
uint16_t stapm_power_limit;
/* time filtered STAPM power limit [W] */
/* time filtered STAPM power limit [mW] */
uint16_t current_stapm_power_limit;
/* Average clocks */
/* time filtered clocks [MHz] */
uint16_t average_gfxclk_frequency;
uint16_t average_socclk_frequency;
uint16_t average_vpeclk_frequency;
@ -1115,7 +1117,7 @@ struct gpu_metrics_v3_0 {
uint16_t average_vclk_frequency;
/* Current clocks */
/* target core frequency */
/* target core frequency [MHz] */
uint16_t current_coreclk[16];
/* CCLK frequency limit enforced on classic cores [MHz] */
uint16_t current_core_maxfreq;

View File

@ -3288,10 +3288,6 @@ static umode_t hwmon_attributes_visible(struct kobject *kobj,
uint32_t gc_ver = amdgpu_ip_version(adev, GC_HWIP, 0);
uint32_t tmp;
/* under multi-vf mode, the hwmon attributes are all not supported */
if (amdgpu_sriov_vf(adev) && !amdgpu_sriov_is_pp_one_vf(adev))
return 0;
/* under pp one vf mode manage of hwmon attributes is not supported */
if (amdgpu_sriov_is_pp_one_vf(adev))
effective_mode &= ~S_IWUSR;
@ -4162,6 +4158,7 @@ err_out:
int amdgpu_pm_sysfs_init(struct amdgpu_device *adev)
{
enum amdgpu_sriov_vf_mode mode;
uint32_t mask = 0;
int ret;
@ -4173,17 +4170,21 @@ int amdgpu_pm_sysfs_init(struct amdgpu_device *adev)
if (adev->pm.dpm_enabled == 0)
return 0;
adev->pm.int_hwmon_dev = hwmon_device_register_with_groups(adev->dev,
DRIVER_NAME, adev,
hwmon_groups);
if (IS_ERR(adev->pm.int_hwmon_dev)) {
ret = PTR_ERR(adev->pm.int_hwmon_dev);
dev_err(adev->dev,
"Unable to register hwmon device: %d\n", ret);
return ret;
mode = amdgpu_virt_get_sriov_vf_mode(adev);
/* under multi-vf mode, the hwmon attributes are all not supported */
if (mode != SRIOV_VF_MODE_MULTI_VF) {
adev->pm.int_hwmon_dev = hwmon_device_register_with_groups(adev->dev,
DRIVER_NAME, adev,
hwmon_groups);
if (IS_ERR(adev->pm.int_hwmon_dev)) {
ret = PTR_ERR(adev->pm.int_hwmon_dev);
dev_err(adev->dev, "Unable to register hwmon device: %d\n", ret);
return ret;
}
}
switch (amdgpu_virt_get_sriov_vf_mode(adev)) {
switch (mode) {
case SRIOV_VF_MODE_ONE_VF:
mask = ATTR_FLAG_ONEVF;
break;

View File

@ -1022,6 +1022,9 @@ static int pp_get_power_limit(void *handle, uint32_t *limit,
*limit /= 100;
}
break;
case PP_PWR_LIMIT_MIN:
*limit = 0;
break;
default:
ret = -EOPNOTSUPP;
break;

View File

@ -367,7 +367,7 @@ typedef struct _ATOM_Tonga_VCE_State_Record {
typedef struct _ATOM_Tonga_VCE_State_Table {
UCHAR ucRevId;
UCHAR ucNumEntries;
ATOM_Tonga_VCE_State_Record entries[1];
ATOM_Tonga_VCE_State_Record entries[];
} ATOM_Tonga_VCE_State_Table;
typedef struct _ATOM_Tonga_PowerTune_Table {
@ -481,7 +481,7 @@ typedef struct _ATOM_Tonga_Hard_Limit_Record {
typedef struct _ATOM_Tonga_Hard_Limit_Table {
UCHAR ucRevId;
UCHAR ucNumEntries;
ATOM_Tonga_Hard_Limit_Record entries[1];
ATOM_Tonga_Hard_Limit_Record entries[];
} ATOM_Tonga_Hard_Limit_Table;
typedef struct _ATOM_Tonga_GPIO_Table {

View File

@ -129,7 +129,7 @@ typedef struct _ATOM_Vega10_State {
typedef struct _ATOM_Vega10_State_Array {
UCHAR ucRevId;
UCHAR ucNumEntries; /* Number of entries. */
ATOM_Vega10_State states[1]; /* Dynamically allocate entries. */
ATOM_Vega10_State states[]; /* Dynamically allocate entries. */
} ATOM_Vega10_State_Array;
typedef struct _ATOM_Vega10_CLK_Dependency_Record {
@ -169,37 +169,37 @@ typedef struct _ATOM_Vega10_GFXCLK_Dependency_Table {
typedef struct _ATOM_Vega10_MCLK_Dependency_Table {
UCHAR ucRevId;
UCHAR ucNumEntries; /* Number of entries. */
ATOM_Vega10_MCLK_Dependency_Record entries[1]; /* Dynamically allocate entries. */
ATOM_Vega10_MCLK_Dependency_Record entries[]; /* Dynamically allocate entries. */
} ATOM_Vega10_MCLK_Dependency_Table;
typedef struct _ATOM_Vega10_SOCCLK_Dependency_Table {
UCHAR ucRevId;
UCHAR ucNumEntries; /* Number of entries. */
ATOM_Vega10_CLK_Dependency_Record entries[1]; /* Dynamically allocate entries. */
ATOM_Vega10_CLK_Dependency_Record entries[]; /* Dynamically allocate entries. */
} ATOM_Vega10_SOCCLK_Dependency_Table;
typedef struct _ATOM_Vega10_DCEFCLK_Dependency_Table {
UCHAR ucRevId;
UCHAR ucNumEntries; /* Number of entries. */
ATOM_Vega10_CLK_Dependency_Record entries[1]; /* Dynamically allocate entries. */
ATOM_Vega10_CLK_Dependency_Record entries[]; /* Dynamically allocate entries. */
} ATOM_Vega10_DCEFCLK_Dependency_Table;
typedef struct _ATOM_Vega10_PIXCLK_Dependency_Table {
UCHAR ucRevId;
UCHAR ucNumEntries; /* Number of entries. */
ATOM_Vega10_CLK_Dependency_Record entries[1]; /* Dynamically allocate entries. */
ATOM_Vega10_CLK_Dependency_Record entries[]; /* Dynamically allocate entries. */
} ATOM_Vega10_PIXCLK_Dependency_Table;
typedef struct _ATOM_Vega10_DISPCLK_Dependency_Table {
UCHAR ucRevId;
UCHAR ucNumEntries; /* Number of entries.*/
ATOM_Vega10_CLK_Dependency_Record entries[1]; /* Dynamically allocate entries. */
ATOM_Vega10_CLK_Dependency_Record entries[]; /* Dynamically allocate entries. */
} ATOM_Vega10_DISPCLK_Dependency_Table;
typedef struct _ATOM_Vega10_PHYCLK_Dependency_Table {
UCHAR ucRevId;
UCHAR ucNumEntries; /* Number of entries. */
ATOM_Vega10_CLK_Dependency_Record entries[1]; /* Dynamically allocate entries. */
ATOM_Vega10_CLK_Dependency_Record entries[]; /* Dynamically allocate entries. */
} ATOM_Vega10_PHYCLK_Dependency_Table;
typedef struct _ATOM_Vega10_MM_Dependency_Record {
@ -213,7 +213,7 @@ typedef struct _ATOM_Vega10_MM_Dependency_Record {
typedef struct _ATOM_Vega10_MM_Dependency_Table {
UCHAR ucRevId;
UCHAR ucNumEntries; /* Number of entries */
ATOM_Vega10_MM_Dependency_Record entries[1]; /* Dynamically allocate entries */
ATOM_Vega10_MM_Dependency_Record entries[]; /* Dynamically allocate entries */
} ATOM_Vega10_MM_Dependency_Table;
typedef struct _ATOM_Vega10_PCIE_Record {
@ -225,7 +225,7 @@ typedef struct _ATOM_Vega10_PCIE_Record {
typedef struct _ATOM_Vega10_PCIE_Table {
UCHAR ucRevId;
UCHAR ucNumEntries; /* Number of entries */
ATOM_Vega10_PCIE_Record entries[1]; /* Dynamically allocate entries. */
ATOM_Vega10_PCIE_Record entries[]; /* Dynamically allocate entries. */
} ATOM_Vega10_PCIE_Table;
typedef struct _ATOM_Vega10_Voltage_Lookup_Record {
@ -235,7 +235,7 @@ typedef struct _ATOM_Vega10_Voltage_Lookup_Record {
typedef struct _ATOM_Vega10_Voltage_Lookup_Table {
UCHAR ucRevId;
UCHAR ucNumEntries; /* Number of entries */
ATOM_Vega10_Voltage_Lookup_Record entries[1]; /* Dynamically allocate entries */
ATOM_Vega10_Voltage_Lookup_Record entries[]; /* Dynamically allocate entries */
} ATOM_Vega10_Voltage_Lookup_Table;
typedef struct _ATOM_Vega10_Fan_Table {
@ -327,7 +327,7 @@ typedef struct _ATOM_Vega10_VCE_State_Record {
typedef struct _ATOM_Vega10_VCE_State_Table {
UCHAR ucRevId;
UCHAR ucNumEntries;
ATOM_Vega10_VCE_State_Record entries[1];
ATOM_Vega10_VCE_State_Record entries[];
} ATOM_Vega10_VCE_State_Table;
typedef struct _ATOM_Vega10_PowerTune_Table {
@ -427,7 +427,7 @@ typedef struct _ATOM_Vega10_Hard_Limit_Record {
typedef struct _ATOM_Vega10_Hard_Limit_Table {
UCHAR ucRevId;
UCHAR ucNumEntries;
ATOM_Vega10_Hard_Limit_Record entries[1];
ATOM_Vega10_Hard_Limit_Record entries[];
} ATOM_Vega10_Hard_Limit_Table;
typedef struct _Vega10_PPTable_Generic_SubTable_Header {

View File

@ -733,7 +733,7 @@ static int smu_early_init(void *handle)
smu->adev = adev;
smu->pm_enabled = !!amdgpu_dpm;
smu->is_apu = false;
smu->smu_baco.state = SMU_BACO_STATE_EXIT;
smu->smu_baco.state = SMU_BACO_STATE_NONE;
smu->smu_baco.platform_support = false;
smu->user_dpm_profile.fan_mode = -1;
@ -1742,10 +1742,31 @@ static int smu_smc_hw_cleanup(struct smu_context *smu)
return 0;
}
static int smu_reset_mp1_state(struct smu_context *smu)
{
struct amdgpu_device *adev = smu->adev;
int ret = 0;
if ((!adev->in_runpm) && (!adev->in_suspend) &&
(!amdgpu_in_reset(adev)))
switch (amdgpu_ip_version(adev, MP1_HWIP, 0)) {
case IP_VERSION(13, 0, 0):
case IP_VERSION(13, 0, 7):
case IP_VERSION(13, 0, 10):
ret = smu_set_mp1_state(smu, PP_MP1_STATE_UNLOAD);
break;
default:
break;
}
return ret;
}
static int smu_hw_fini(void *handle)
{
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
struct smu_context *smu = adev->powerplay.pp_handle;
int ret;
if (amdgpu_sriov_vf(adev) && !amdgpu_sriov_is_pp_one_vf(adev))
return 0;
@ -1763,7 +1784,15 @@ static int smu_hw_fini(void *handle)
adev->pm.dpm_enabled = false;
return smu_smc_hw_cleanup(smu);
ret = smu_smc_hw_cleanup(smu);
if (ret)
return ret;
ret = smu_reset_mp1_state(smu);
if (ret)
return ret;
return 0;
}
static void smu_late_fini(void *handle)

View File

@ -419,6 +419,7 @@ enum smu_reset_mode {
enum smu_baco_state {
SMU_BACO_STATE_ENTER = 0,
SMU_BACO_STATE_EXIT,
SMU_BACO_STATE_NONE,
};
struct smu_baco_context {

View File

@ -150,97 +150,39 @@ typedef struct {
} DpmClocks_t;
typedef struct {
uint16_t CoreFrequency[16]; //Target core frequency [MHz]
uint16_t CorePower[16]; //CAC calculated core power [W] [Q8.8]
uint16_t CoreTemperature[16]; //TSEN measured core temperature [C] [Q8.8]
uint16_t GfxTemperature; //TSEN measured GFX temperature [C] [Q8.8]
uint16_t SocTemperature; //TSEN measured SOC temperature [C] [Q8.8]
uint16_t StapmOpnLimit; //Maximum IRM defined STAPM power limit [W] [Q8.8]
uint16_t StapmCurrentLimit; //Time filtered STAPM power limit [W] [Q8.8]
uint16_t InfrastructureCpuMaxFreq; //CCLK frequency limit enforced on classic cores [MHz]
uint16_t InfrastructureGfxMaxFreq; //GFXCLK frequency limit enforced on GFX [MHz]
uint16_t SkinTemp; //Maximum skin temperature reported by APU and HS2 chassis sensors [C] [Q8.8]
uint16_t AverageGfxclkFrequency; //Time filtered target GFXCLK frequency [MHz]
uint16_t AverageFclkFrequency; //Time filtered target FCLK frequency [MHz]
uint16_t AverageGfxActivity; //Time filtered GFX busy % [0-100] [Q8.8]
uint16_t AverageSocclkFrequency; //Time filtered target SOCCLK frequency [MHz]
uint16_t AverageVclkFrequency; //Time filtered target VCLK frequency [MHz]
uint16_t AverageVcnActivity; //Time filtered VCN busy % [0-100] [Q8.8]
uint16_t AverageVpeclkFrequency; //Time filtered target VPECLK frequency [MHz]
uint16_t AverageIpuclkFrequency; //Time filtered target IPUCLK frequency [MHz]
uint16_t AverageIpuBusy[8]; //Time filtered IPU per-column busy % [0-100] [Q8.8]
uint16_t AverageDRAMReads; //Time filtered DRAM read bandwidth [GB/sec] [Q8.8]
uint16_t AverageDRAMWrites; //Time filtered DRAM write bandwidth [GB/sec] [Q8.8]
uint16_t AverageCoreC0Residency[16]; //Time filtered per-core C0 residency % [0-100] [Q8.8]
uint16_t IpuPower; //Time filtered IPU power [W] [Q8.8]
uint32_t ApuPower; //Time filtered APU power [W] [Q24.8]
uint32_t dGpuPower; //Time filtered dGPU power [W] [Q24.8]
uint32_t AverageSocketPower; //Time filtered power used for PPT/STAPM [APU+dGPU] [W] [Q24.8]
uint32_t AverageCorePower; //Time filtered sum of core power across all cores in the socket [W] [Q24.8]
uint32_t FilterAlphaValue; //Metrics table alpha filter time constant [us]
uint32_t MetricsCounter; //Counter that is incremented on every metrics table update [PM_TIMER cycles]
uint16_t CoreFrequency[16]; //Target core frequency [MHz]
uint16_t CorePower[16]; //CAC calculated core power [mW]
uint16_t CoreTemperature[16]; //TSEN measured core temperature [centi-C]
uint16_t GfxTemperature; //TSEN measured GFX temperature [centi-C]
uint16_t SocTemperature; //TSEN measured SOC temperature [centi-C]
uint16_t StapmOpnLimit; //Maximum IRM defined STAPM power limit [mW]
uint16_t StapmCurrentLimit; //Time filtered STAPM power limit [mW]
uint16_t InfrastructureCpuMaxFreq; //CCLK frequency limit enforced on classic cores [MHz]
uint16_t InfrastructureGfxMaxFreq; //GFXCLK frequency limit enforced on GFX [MHz]
uint16_t SkinTemp; //Maximum skin temperature reported by APU and HS2 chassis sensors [centi-C]
uint16_t GfxclkFrequency; //Time filtered target GFXCLK frequency [MHz]
uint16_t FclkFrequency; //Time filtered target FCLK frequency [MHz]
uint16_t GfxActivity; //Time filtered GFX busy % [0-100]
uint16_t SocclkFrequency; //Time filtered target SOCCLK frequency [MHz]
uint16_t VclkFrequency; //Time filtered target VCLK frequency [MHz]
uint16_t VcnActivity; //Time filtered VCN busy % [0-100]
uint16_t VpeclkFrequency; //Time filtered target VPECLK frequency [MHz]
uint16_t IpuclkFrequency; //Time filtered target IPUCLK frequency [MHz]
uint16_t IpuBusy[8]; //Time filtered IPU per-column busy % [0-100]
uint16_t DRAMReads; //Time filtered DRAM read bandwidth [MB/sec]
uint16_t DRAMWrites; //Time filtered DRAM write bandwidth [MB/sec]
uint16_t CoreC0Residency[16]; //Time filtered per-core C0 residency % [0-100]
uint16_t IpuPower; //Time filtered IPU power [mW]
uint32_t ApuPower; //Time filtered APU power [mW]
uint32_t GfxPower; //Time filtered GFX power [mW]
uint32_t dGpuPower; //Time filtered dGPU power [mW]
uint32_t SocketPower; //Time filtered power used for PPT/STAPM [APU+dGPU] [mW]
uint32_t AllCorePower; //Time filtered sum of core power across all cores in the socket [mW]
uint32_t FilterAlphaValue; //Metrics table alpha filter time constant [us]
uint32_t MetricsCounter; //Counter that is incremented on every metrics table update [PM_TIMER cycles]
uint32_t spare[16];
} SmuMetrics_t;
typedef struct {
uint16_t GfxclkFrequency; //[MHz]
uint16_t SocclkFrequency; //[MHz]
uint16_t VclkFrequency; //[MHz]
uint16_t DclkFrequency; //[MHz]
uint16_t MemclkFrequency; //[MHz]
uint16_t spare;
uint16_t UvdActivity; //[centi]
uint16_t GfxActivity; //[centi]
uint16_t Voltage[2]; //[mV] indices: VDDCR_VDD, VDDCR_SOC
uint16_t Current[2]; //[mA] indices: VDDCR_VDD, VDDCR_SOC
uint16_t Power[2]; //[mW] indices: VDDCR_VDD, VDDCR_SOC
uint16_t CoreFrequency[8]; //[MHz]
uint16_t CorePower[8]; //[mW]
uint16_t CoreTemperature[8]; //[centi-Celsius]
uint16_t L3Frequency[2]; //[MHz]
uint16_t L3Temperature[2]; //[centi-Celsius]
uint16_t spare2[24];
uint16_t GfxTemperature; //[centi-Celsius]
uint16_t SocTemperature; //[centi-Celsius]
uint16_t ThrottlerStatus;
uint16_t CurrentSocketPower; //[mW]
uint16_t StapmOpnLimit; //[W]
uint16_t StapmCurrentLimit; //[W]
uint32_t ApuPower; //[mW]
uint32_t dGpuPower; //[mW]
uint16_t VddTdcValue; //[mA]
uint16_t SocTdcValue; //[mA]
uint16_t VddEdcValue; //[mA]
uint16_t SocEdcValue; //[mA]
uint16_t InfrastructureCpuMaxFreq; //[MHz]
uint16_t InfrastructureGfxMaxFreq; //[MHz]
uint16_t SkinTemp;
uint16_t DeviceState;
uint16_t CurTemp; //[centi-Celsius]
uint16_t FilterAlphaValue; //[m]
uint16_t AverageGfxclkFrequency;
uint16_t AverageFclkFrequency;
uint16_t AverageGfxActivity;
uint16_t AverageSocclkFrequency;
uint16_t AverageVclkFrequency;
uint16_t AverageVcnActivity;
uint16_t AverageDRAMReads; //Filtered DF Bandwidth::DRAM Reads
uint16_t AverageDRAMWrites; //Filtered DF Bandwidth::DRAM Writes
uint16_t AverageSocketPower; //Filtered value of CurrentSocketPower
uint16_t AverageCorePower[2]; //Filtered of [sum of CorePower[8] per ccx])
uint16_t AverageCoreC0Residency[16]; //Filtered of [average C0 residency % per core]
uint16_t spare1;
uint32_t MetricsCounter; //Counts the # of metrics table parameter reads per update to the metrics table, i.e. if the metrics table update happens every 1 second, this value could be up to 1000 if the smu collected metrics data every cycle, or as low as 0 if the smu was asleep the whole time. Reset to 0 after writing.
} SmuMetrics_legacy_t;
//ISP tile definitions
typedef enum {
TILE_XTILE = 0, //ONO0

View File

@ -299,5 +299,7 @@ int smu_v13_0_update_pcie_parameters(struct smu_context *smu,
uint8_t pcie_gen_cap,
uint8_t pcie_width_cap);
int smu_v13_0_disable_pmfw_state(struct smu_context *smu);
#endif
#endif

View File

@ -234,24 +234,15 @@ static int vangogh_tables_init(struct smu_context *smu)
PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM);
SMU_TABLE_INIT(tables, SMU_TABLE_ACTIVITY_MONITOR_COEFF, sizeof(DpmActivityMonitorCoeffExt_t),
PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM);
SMU_TABLE_INIT(tables, SMU_TABLE_SMU_METRICS, max(sizeof(SmuMetrics_t), sizeof(SmuMetrics_legacy_t)),
PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM);
if (smu->smc_fw_if_version < 0x3) {
SMU_TABLE_INIT(tables, SMU_TABLE_SMU_METRICS, sizeof(SmuMetrics_legacy_t),
PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM);
smu_table->metrics_table = kzalloc(sizeof(SmuMetrics_legacy_t), GFP_KERNEL);
} else {
SMU_TABLE_INIT(tables, SMU_TABLE_SMU_METRICS, sizeof(SmuMetrics_t),
PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM);
smu_table->metrics_table = kzalloc(sizeof(SmuMetrics_t), GFP_KERNEL);
}
smu_table->metrics_table = kzalloc(max(sizeof(SmuMetrics_t), sizeof(SmuMetrics_legacy_t)), GFP_KERNEL);
if (!smu_table->metrics_table)
goto err0_out;
smu_table->metrics_time = 0;
if (smu->smc_fw_version >= 0x043F3E00)
smu_table->gpu_metrics_table_size = sizeof(struct gpu_metrics_v2_3);
else
smu_table->gpu_metrics_table_size = sizeof(struct gpu_metrics_v2_2);
smu_table->gpu_metrics_table_size = max(sizeof(struct gpu_metrics_v2_3), sizeof(struct gpu_metrics_v2_2));
smu_table->gpu_metrics_table = kzalloc(smu_table->gpu_metrics_table_size, GFP_KERNEL);
if (!smu_table->gpu_metrics_table)
goto err1_out;

View File

@ -2477,3 +2477,16 @@ int smu_v13_0_update_pcie_parameters(struct smu_context *smu,
return 0;
}
int smu_v13_0_disable_pmfw_state(struct smu_context *smu)
{
int ret;
struct amdgpu_device *adev = smu->adev;
WREG32_PCIE(MP1_Public | (smnMP1_FIRMWARE_FLAGS & 0xffffffff), 0);
ret = RREG32_PCIE(MP1_Public |
(smnMP1_FIRMWARE_FLAGS & 0xffffffff));
return ret == 0 ? 0 : -EINVAL;
}

View File

@ -354,12 +354,12 @@ static int smu_v13_0_0_check_powerplay_table(struct smu_context *smu)
if (powerplay_table->platform_caps & SMU_13_0_0_PP_PLATFORM_CAP_HARDWAREDC)
smu->dc_controlled_by_gpio = true;
if (powerplay_table->platform_caps & SMU_13_0_0_PP_PLATFORM_CAP_BACO ||
powerplay_table->platform_caps & SMU_13_0_0_PP_PLATFORM_CAP_MACO)
if (powerplay_table->platform_caps & SMU_13_0_0_PP_PLATFORM_CAP_BACO) {
smu_baco->platform_support = true;
if (powerplay_table->platform_caps & SMU_13_0_0_PP_PLATFORM_CAP_MACO)
smu_baco->maco_support = true;
if (powerplay_table->platform_caps & SMU_13_0_0_PP_PLATFORM_CAP_MACO)
smu_baco->maco_support = true;
}
if (!overdrive_lowerlimits->FeatureCtrlMask ||
!overdrive_upperlimits->FeatureCtrlMask)
@ -2530,38 +2530,10 @@ static int smu_v13_0_0_set_power_profile_mode(struct smu_context *smu,
}
}
if (smu->power_profile_mode == PP_SMC_POWER_PROFILE_COMPUTE &&
(((smu->adev->pdev->device == 0x744C) && (smu->adev->pdev->revision == 0xC8)) ||
((smu->adev->pdev->device == 0x744C) && (smu->adev->pdev->revision == 0xCC)))) {
ret = smu_cmn_update_table(smu,
SMU_TABLE_ACTIVITY_MONITOR_COEFF,
WORKLOAD_PPLIB_COMPUTE_BIT,
(void *)(&activity_monitor_external),
false);
if (ret) {
dev_err(smu->adev->dev, "[%s] Failed to get activity monitor!", __func__);
return ret;
}
ret = smu_cmn_update_table(smu,
SMU_TABLE_ACTIVITY_MONITOR_COEFF,
WORKLOAD_PPLIB_CUSTOM_BIT,
(void *)(&activity_monitor_external),
true);
if (ret) {
dev_err(smu->adev->dev, "[%s] Failed to set activity monitor!", __func__);
return ret;
}
workload_type = smu_cmn_to_asic_specific_index(smu,
CMN2ASIC_MAPPING_WORKLOAD,
PP_SMC_POWER_PROFILE_CUSTOM);
} else {
/* conv PP_SMC_POWER_PROFILE* to WORKLOAD_PPLIB_*_BIT */
workload_type = smu_cmn_to_asic_specific_index(smu,
/* conv PP_SMC_POWER_PROFILE* to WORKLOAD_PPLIB_*_BIT */
workload_type = smu_cmn_to_asic_specific_index(smu,
CMN2ASIC_MAPPING_WORKLOAD,
smu->power_profile_mode);
}
if (workload_type < 0)
return -EINVAL;
@ -2602,14 +2574,20 @@ static int smu_v13_0_0_baco_enter(struct smu_context *smu)
static int smu_v13_0_0_baco_exit(struct smu_context *smu)
{
struct amdgpu_device *adev = smu->adev;
int ret;
if (adev->in_runpm && smu_cmn_is_audio_func_enabled(adev)) {
/* Wait for PMFW handling for the Dstate change */
usleep_range(10000, 11000);
return smu_v13_0_baco_set_armd3_sequence(smu, BACO_SEQ_ULPS);
ret = smu_v13_0_baco_set_armd3_sequence(smu, BACO_SEQ_ULPS);
} else {
return smu_v13_0_baco_exit(smu);
ret = smu_v13_0_baco_exit(smu);
}
if (!ret)
adev->gfx.is_poweron = false;
return ret;
}
static bool smu_v13_0_0_is_mode1_reset_supported(struct smu_context *smu)
@ -2794,7 +2772,13 @@ static int smu_v13_0_0_set_mp1_state(struct smu_context *smu,
switch (mp1_state) {
case PP_MP1_STATE_UNLOAD:
ret = smu_cmn_set_mp1_state(smu, mp1_state);
ret = smu_cmn_send_smc_msg_with_param(smu,
SMU_MSG_PrepareMp1ForUnload,
0x55, NULL);
if (!ret && smu->smu_baco.state == SMU_BACO_STATE_EXIT)
ret = smu_v13_0_disable_pmfw_state(smu);
break;
default:
/* Ignore others */

View File

@ -270,7 +270,7 @@ static int smu_v13_0_6_init_microcode(struct smu_context *smu)
struct amdgpu_device *adev = smu->adev;
uint32_t p2s_table_id = P2S_TABLE_ID_A;
int ret = 0, i, p2stable_count;
char ucode_prefix[30];
char ucode_prefix[15];
char fw_name[30];
/* No need to load P2S tables in IOV mode */

View File

@ -346,12 +346,13 @@ static int smu_v13_0_7_check_powerplay_table(struct smu_context *smu)
if (powerplay_table->platform_caps & SMU_13_0_7_PP_PLATFORM_CAP_HARDWAREDC)
smu->dc_controlled_by_gpio = true;
if (powerplay_table->platform_caps & SMU_13_0_7_PP_PLATFORM_CAP_BACO ||
powerplay_table->platform_caps & SMU_13_0_7_PP_PLATFORM_CAP_MACO)
if (powerplay_table->platform_caps & SMU_13_0_7_PP_PLATFORM_CAP_BACO) {
smu_baco->platform_support = true;
if (smu_baco->platform_support && (BoardTable->HsrEnabled || BoardTable->VddqOffEnabled))
smu_baco->maco_support = true;
if ((powerplay_table->platform_caps & SMU_13_0_7_PP_PLATFORM_CAP_MACO)
&& (BoardTable->HsrEnabled || BoardTable->VddqOffEnabled))
smu_baco->maco_support = true;
}
if (!overdrive_lowerlimits->FeatureCtrlMask ||
!overdrive_upperlimits->FeatureCtrlMask)
@ -2498,7 +2499,13 @@ static int smu_v13_0_7_set_mp1_state(struct smu_context *smu,
switch (mp1_state) {
case PP_MP1_STATE_UNLOAD:
ret = smu_cmn_set_mp1_state(smu, mp1_state);
ret = smu_cmn_send_smc_msg_with_param(smu,
SMU_MSG_PrepareMp1ForUnload,
0x55, NULL);
if (!ret && smu->smu_baco.state == SMU_BACO_STATE_EXIT)
ret = smu_v13_0_disable_pmfw_state(smu);
break;
default:
/* Ignore others */
@ -2524,14 +2531,20 @@ static int smu_v13_0_7_baco_enter(struct smu_context *smu)
static int smu_v13_0_7_baco_exit(struct smu_context *smu)
{
struct amdgpu_device *adev = smu->adev;
int ret;
if (adev->in_runpm && smu_cmn_is_audio_func_enabled(adev)) {
/* Wait for PMFW handling for the Dstate change */
usleep_range(10000, 11000);
return smu_v13_0_baco_set_armd3_sequence(smu, BACO_SEQ_ULPS);
ret = smu_v13_0_baco_set_armd3_sequence(smu, BACO_SEQ_ULPS);
} else {
return smu_v13_0_baco_exit(smu);
ret = smu_v13_0_baco_exit(smu);
}
if (!ret)
adev->gfx.is_poweron = false;
return ret;
}
static bool smu_v13_0_7_is_mode1_reset_supported(struct smu_context *smu)

View File

@ -57,7 +57,7 @@ int smu_v14_0_init_microcode(struct smu_context *smu)
{
struct amdgpu_device *adev = smu->adev;
char fw_name[30];
char ucode_prefix[30];
char ucode_prefix[15];
int err = 0;
const struct smc_firmware_header_v1_0 *hdr;
const struct common_firmware_header *header;
@ -229,6 +229,8 @@ int smu_v14_0_check_fw_version(struct smu_context *smu)
smu->smc_driver_if_version = SMU14_DRIVER_IF_VERSION_SMU_V14_0_2;
break;
case IP_VERSION(14, 0, 0):
if ((smu->smc_fw_version < 0x5d3a00))
dev_warn(smu->adev->dev, "The PMFW version(%x) is behind in this BIOS!\n", smu->smc_fw_version);
smu->smc_driver_if_version = SMU14_DRIVER_IF_VERSION_SMU_V14_0_0;
break;
default:

View File

@ -156,15 +156,10 @@ static int smu_v14_0_0_init_smc_tables(struct smu_context *smu)
PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM);
SMU_TABLE_INIT(tables, SMU_TABLE_DPMCLOCKS, sizeof(DpmClocks_t),
PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM);
if (smu->smc_fw_version > 0x5d3500) {
SMU_TABLE_INIT(tables, SMU_TABLE_SMU_METRICS, sizeof(SmuMetrics_t),
PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM);
smu_table->metrics_table = kzalloc(sizeof(SmuMetrics_t), GFP_KERNEL);
} else {
SMU_TABLE_INIT(tables, SMU_TABLE_SMU_METRICS, sizeof(SmuMetrics_legacy_t),
PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM);
smu_table->metrics_table = kzalloc(sizeof(SmuMetrics_legacy_t), GFP_KERNEL);
}
SMU_TABLE_INIT(tables, SMU_TABLE_SMU_METRICS, sizeof(SmuMetrics_t),
PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM);
smu_table->metrics_table = kzalloc(sizeof(SmuMetrics_t), GFP_KERNEL);
if (!smu_table->metrics_table)
goto err0_out;
smu_table->metrics_time = 0;
@ -177,10 +172,7 @@ static int smu_v14_0_0_init_smc_tables(struct smu_context *smu)
if (!smu_table->watermarks_table)
goto err2_out;
if (smu->smc_fw_version > 0x5d3500)
smu_table->gpu_metrics_table_size = sizeof(struct gpu_metrics_v3_0);
else
smu_table->gpu_metrics_table_size = sizeof(struct gpu_metrics_v2_1);
smu_table->gpu_metrics_table_size = sizeof(struct gpu_metrics_v3_0);
smu_table->gpu_metrics_table = kzalloc(smu_table->gpu_metrics_table_size, GFP_KERNEL);
if (!smu_table->gpu_metrics_table)
goto err3_out;
@ -242,13 +234,13 @@ static int smu_v14_0_0_get_smu_metrics_data(struct smu_context *smu,
switch (member) {
case METRICS_AVERAGE_GFXCLK:
*value = metrics->AverageGfxclkFrequency;
*value = metrics->GfxclkFrequency;
break;
case METRICS_AVERAGE_SOCCLK:
*value = metrics->AverageSocclkFrequency;
*value = metrics->SocclkFrequency;
break;
case METRICS_AVERAGE_VCLK:
*value = metrics->AverageVclkFrequency;
*value = metrics->VclkFrequency;
break;
case METRICS_AVERAGE_DCLK:
*value = 0;
@ -257,25 +249,25 @@ static int smu_v14_0_0_get_smu_metrics_data(struct smu_context *smu,
*value = 0;
break;
case METRICS_AVERAGE_FCLK:
*value = metrics->AverageFclkFrequency;
*value = metrics->FclkFrequency;
break;
case METRICS_AVERAGE_GFXACTIVITY:
*value = metrics->AverageGfxActivity >> 8;
*value = metrics->GfxActivity / 100;
break;
case METRICS_AVERAGE_VCNACTIVITY:
*value = metrics->AverageVcnActivity >> 8;
*value = metrics->VcnActivity / 100;
break;
case METRICS_AVERAGE_SOCKETPOWER:
case METRICS_CURR_SOCKETPOWER:
*value = (metrics->AverageSocketPower & 0xff00) +
((metrics->AverageSocketPower & 0xff) * 100 >> 8);
*value = (metrics->SocketPower / 1000 << 8) +
(metrics->SocketPower % 1000 / 10);
break;
case METRICS_TEMPERATURE_EDGE:
*value = (metrics->GfxTemperature >> 8) *
*value = metrics->GfxTemperature / 100 *
SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
break;
case METRICS_TEMPERATURE_HOTSPOT:
*value = (metrics->SocTemperature >> 8) *
*value = metrics->SocTemperature / 100 *
SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
break;
case METRICS_THROTTLER_STATUS:
@ -317,107 +309,6 @@ static int smu_v14_0_0_get_smu_metrics_data(struct smu_context *smu,
return ret;
}
static int smu_v14_0_0_legacy_get_smu_metrics_data(struct smu_context *smu,
MetricsMember_t member,
uint32_t *value)
{
struct smu_table_context *smu_table = &smu->smu_table;
SmuMetrics_legacy_t *metrics = (SmuMetrics_legacy_t *)smu_table->metrics_table;
int ret = 0;
ret = smu_cmn_get_metrics_table(smu, NULL, false);
if (ret)
return ret;
switch (member) {
case METRICS_AVERAGE_GFXCLK:
*value = metrics->GfxclkFrequency;
break;
case METRICS_AVERAGE_SOCCLK:
*value = metrics->SocclkFrequency;
break;
case METRICS_AVERAGE_VCLK:
*value = metrics->VclkFrequency;
break;
case METRICS_AVERAGE_DCLK:
*value = metrics->DclkFrequency;
break;
case METRICS_AVERAGE_UCLK:
*value = metrics->MemclkFrequency;
break;
case METRICS_AVERAGE_GFXACTIVITY:
*value = metrics->GfxActivity / 100;
break;
case METRICS_AVERAGE_FCLK:
*value = metrics->AverageFclkFrequency;
break;
case METRICS_AVERAGE_VCNACTIVITY:
*value = metrics->UvdActivity;
break;
case METRICS_AVERAGE_SOCKETPOWER:
*value = (metrics->AverageSocketPower << 8) / 1000;
break;
case METRICS_CURR_SOCKETPOWER:
*value = (metrics->CurrentSocketPower << 8) / 1000;
break;
case METRICS_TEMPERATURE_EDGE:
*value = metrics->GfxTemperature / 100 *
SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
break;
case METRICS_TEMPERATURE_HOTSPOT:
*value = metrics->SocTemperature / 100 *
SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
break;
case METRICS_THROTTLER_STATUS:
*value = metrics->ThrottlerStatus;
break;
case METRICS_VOLTAGE_VDDGFX:
*value = metrics->Voltage[0];
break;
case METRICS_VOLTAGE_VDDSOC:
*value = metrics->Voltage[1];
break;
case METRICS_SS_APU_SHARE:
/* return the percentage of APU power with respect to APU's power limit.
* percentage is reported, this isn't boost value. Smartshift power
* boost/shift is only when the percentage is more than 100.
*/
if (metrics->StapmOpnLimit > 0)
*value = (metrics->ApuPower * 100) / metrics->StapmOpnLimit;
else
*value = 0;
break;
case METRICS_SS_DGPU_SHARE:
/* return the percentage of dGPU power with respect to dGPU's power limit.
* percentage is reported, this isn't boost value. Smartshift power
* boost/shift is only when the percentage is more than 100.
*/
if ((metrics->dGpuPower > 0) &&
(metrics->StapmCurrentLimit > metrics->StapmOpnLimit))
*value = (metrics->dGpuPower * 100) /
(metrics->StapmCurrentLimit - metrics->StapmOpnLimit);
else
*value = 0;
break;
default:
*value = UINT_MAX;
break;
}
return ret;
}
static int smu_v14_0_0_common_get_smu_metrics_data(struct smu_context *smu,
MetricsMember_t member,
uint32_t *value)
{
if (smu->smc_fw_version > 0x5d3500)
return smu_v14_0_0_get_smu_metrics_data(smu, member, value);
else
return smu_v14_0_0_legacy_get_smu_metrics_data(smu, member, value);
}
static int smu_v14_0_0_read_sensor(struct smu_context *smu,
enum amd_pp_sensors sensor,
void *data, uint32_t *size)
@ -429,69 +320,69 @@ static int smu_v14_0_0_read_sensor(struct smu_context *smu,
switch (sensor) {
case AMDGPU_PP_SENSOR_GPU_LOAD:
ret = smu_v14_0_0_common_get_smu_metrics_data(smu,
ret = smu_v14_0_0_get_smu_metrics_data(smu,
METRICS_AVERAGE_GFXACTIVITY,
(uint32_t *)data);
*size = 4;
break;
case AMDGPU_PP_SENSOR_GPU_AVG_POWER:
ret = smu_v14_0_0_common_get_smu_metrics_data(smu,
ret = smu_v14_0_0_get_smu_metrics_data(smu,
METRICS_AVERAGE_SOCKETPOWER,
(uint32_t *)data);
*size = 4;
break;
case AMDGPU_PP_SENSOR_GPU_INPUT_POWER:
ret = smu_v14_0_0_common_get_smu_metrics_data(smu,
ret = smu_v14_0_0_get_smu_metrics_data(smu,
METRICS_CURR_SOCKETPOWER,
(uint32_t *)data);
*size = 4;
break;
case AMDGPU_PP_SENSOR_EDGE_TEMP:
ret = smu_v14_0_0_common_get_smu_metrics_data(smu,
ret = smu_v14_0_0_get_smu_metrics_data(smu,
METRICS_TEMPERATURE_EDGE,
(uint32_t *)data);
*size = 4;
break;
case AMDGPU_PP_SENSOR_HOTSPOT_TEMP:
ret = smu_v14_0_0_common_get_smu_metrics_data(smu,
ret = smu_v14_0_0_get_smu_metrics_data(smu,
METRICS_TEMPERATURE_HOTSPOT,
(uint32_t *)data);
*size = 4;
break;
case AMDGPU_PP_SENSOR_GFX_MCLK:
ret = smu_v14_0_0_common_get_smu_metrics_data(smu,
ret = smu_v14_0_0_get_smu_metrics_data(smu,
METRICS_AVERAGE_UCLK,
(uint32_t *)data);
*(uint32_t *)data *= 100;
*size = 4;
break;
case AMDGPU_PP_SENSOR_GFX_SCLK:
ret = smu_v14_0_0_common_get_smu_metrics_data(smu,
ret = smu_v14_0_0_get_smu_metrics_data(smu,
METRICS_AVERAGE_GFXCLK,
(uint32_t *)data);
*(uint32_t *)data *= 100;
*size = 4;
break;
case AMDGPU_PP_SENSOR_VDDGFX:
ret = smu_v14_0_0_common_get_smu_metrics_data(smu,
ret = smu_v14_0_0_get_smu_metrics_data(smu,
METRICS_VOLTAGE_VDDGFX,
(uint32_t *)data);
*size = 4;
break;
case AMDGPU_PP_SENSOR_VDDNB:
ret = smu_v14_0_0_common_get_smu_metrics_data(smu,
ret = smu_v14_0_0_get_smu_metrics_data(smu,
METRICS_VOLTAGE_VDDSOC,
(uint32_t *)data);
*size = 4;
break;
case AMDGPU_PP_SENSOR_SS_APU_SHARE:
ret = smu_v14_0_0_common_get_smu_metrics_data(smu,
ret = smu_v14_0_0_get_smu_metrics_data(smu,
METRICS_SS_APU_SHARE,
(uint32_t *)data);
*size = 4;
break;
case AMDGPU_PP_SENSOR_SS_DGPU_SHARE:
ret = smu_v14_0_0_common_get_smu_metrics_data(smu,
ret = smu_v14_0_0_get_smu_metrics_data(smu,
METRICS_SS_DGPU_SHARE,
(uint32_t *)data);
*size = 4;
@ -588,7 +479,7 @@ static ssize_t smu_v14_0_0_get_gpu_metrics(struct smu_context *smu,
if (ret)
return ret;
smu_cmn_init_soft_gpu_metrics(gpu_metrics, 2, 1);
smu_cmn_init_soft_gpu_metrics(gpu_metrics, 3, 0);
gpu_metrics->temperature_gfx = metrics.GfxTemperature;
gpu_metrics->temperature_soc = metrics.SocTemperature;
@ -597,32 +488,33 @@ static ssize_t smu_v14_0_0_get_gpu_metrics(struct smu_context *smu,
sizeof(uint16_t) * 16);
gpu_metrics->temperature_skin = metrics.SkinTemp;
gpu_metrics->average_gfx_activity = metrics.AverageGfxActivity;
gpu_metrics->average_vcn_activity = metrics.AverageVcnActivity;
gpu_metrics->average_gfx_activity = metrics.GfxActivity;
gpu_metrics->average_vcn_activity = metrics.VcnActivity;
memcpy(&gpu_metrics->average_ipu_activity[0],
&metrics.AverageIpuBusy[0],
&metrics.IpuBusy[0],
sizeof(uint16_t) * 8);
memcpy(&gpu_metrics->average_core_c0_activity[0],
&metrics.AverageCoreC0Residency[0],
&metrics.CoreC0Residency[0],
sizeof(uint16_t) * 16);
gpu_metrics->average_dram_reads = metrics.AverageDRAMReads;
gpu_metrics->average_dram_writes = metrics.AverageDRAMWrites;
gpu_metrics->average_dram_reads = metrics.DRAMReads;
gpu_metrics->average_dram_writes = metrics.DRAMWrites;
gpu_metrics->average_socket_power = metrics.AverageSocketPower;
gpu_metrics->average_socket_power = metrics.SocketPower;
gpu_metrics->average_ipu_power = metrics.IpuPower;
gpu_metrics->average_apu_power = metrics.ApuPower;
gpu_metrics->average_gfx_power = metrics.GfxPower;
gpu_metrics->average_dgpu_power = metrics.dGpuPower;
gpu_metrics->average_core_power = metrics.AverageCorePower;
memcpy(&gpu_metrics->core_power[0],
gpu_metrics->average_all_core_power = metrics.AllCorePower;
memcpy(&gpu_metrics->average_core_power[0],
&metrics.CorePower[0],
sizeof(uint16_t) * 16);
gpu_metrics->average_gfxclk_frequency = metrics.AverageGfxclkFrequency;
gpu_metrics->average_socclk_frequency = metrics.AverageSocclkFrequency;
gpu_metrics->average_vpeclk_frequency = metrics.AverageVpeclkFrequency;
gpu_metrics->average_fclk_frequency = metrics.AverageFclkFrequency;
gpu_metrics->average_vclk_frequency = metrics.AverageVclkFrequency;
gpu_metrics->average_ipuclk_frequency = metrics.AverageIpuclkFrequency;
gpu_metrics->average_gfxclk_frequency = metrics.GfxclkFrequency;
gpu_metrics->average_socclk_frequency = metrics.SocclkFrequency;
gpu_metrics->average_vpeclk_frequency = metrics.VpeclkFrequency;
gpu_metrics->average_fclk_frequency = metrics.FclkFrequency;
gpu_metrics->average_vclk_frequency = metrics.VclkFrequency;
gpu_metrics->average_ipuclk_frequency = metrics.IpuclkFrequency;
memcpy(&gpu_metrics->current_coreclk[0],
&metrics.CoreFrequency[0],
@ -638,68 +530,6 @@ static ssize_t smu_v14_0_0_get_gpu_metrics(struct smu_context *smu,
return sizeof(struct gpu_metrics_v3_0);
}
static ssize_t smu_v14_0_0_get_legacy_gpu_metrics(struct smu_context *smu,
void **table)
{
struct smu_table_context *smu_table = &smu->smu_table;
struct gpu_metrics_v2_1 *gpu_metrics =
(struct gpu_metrics_v2_1 *)smu_table->gpu_metrics_table;
SmuMetrics_legacy_t metrics;
int ret = 0;
ret = smu_cmn_get_metrics_table(smu, &metrics, true);
if (ret)
return ret;
smu_cmn_init_soft_gpu_metrics(gpu_metrics, 2, 1);
gpu_metrics->temperature_gfx = metrics.GfxTemperature;
gpu_metrics->temperature_soc = metrics.SocTemperature;
memcpy(&gpu_metrics->temperature_core[0],
&metrics.CoreTemperature[0],
sizeof(uint16_t) * 8);
gpu_metrics->temperature_l3[0] = metrics.L3Temperature[0];
gpu_metrics->temperature_l3[1] = metrics.L3Temperature[1];
gpu_metrics->average_gfx_activity = metrics.GfxActivity;
gpu_metrics->average_mm_activity = metrics.UvdActivity;
gpu_metrics->average_socket_power = metrics.CurrentSocketPower;
gpu_metrics->average_gfx_power = metrics.Power[0];
gpu_metrics->average_soc_power = metrics.Power[1];
memcpy(&gpu_metrics->average_core_power[0],
&metrics.CorePower[0],
sizeof(uint16_t) * 8);
gpu_metrics->average_gfxclk_frequency = metrics.GfxclkFrequency;
gpu_metrics->average_socclk_frequency = metrics.SocclkFrequency;
gpu_metrics->average_uclk_frequency = metrics.MemclkFrequency;
gpu_metrics->average_fclk_frequency = metrics.MemclkFrequency;
gpu_metrics->average_vclk_frequency = metrics.VclkFrequency;
gpu_metrics->average_dclk_frequency = metrics.DclkFrequency;
memcpy(&gpu_metrics->current_coreclk[0],
&metrics.CoreFrequency[0],
sizeof(uint16_t) * 8);
gpu_metrics->throttle_status = metrics.ThrottlerStatus;
gpu_metrics->system_clock_counter = ktime_get_boottime_ns();
*table = (void *)gpu_metrics;
return sizeof(struct gpu_metrics_v2_1);
}
static ssize_t smu_v14_0_0_common_get_gpu_metrics(struct smu_context *smu,
void **table)
{
if (smu->smc_fw_version > 0x5d3500)
return smu_v14_0_0_get_gpu_metrics(smu, table);
else
return smu_v14_0_0_get_legacy_gpu_metrics(smu, table);
}
static int smu_v14_0_0_mode2_reset(struct smu_context *smu)
{
int ret;
@ -928,7 +758,7 @@ static int smu_v14_0_0_get_current_clk_freq(struct smu_context *smu,
return -EINVAL;
}
return smu_v14_0_0_common_get_smu_metrics_data(smu, member_type, value);
return smu_v14_0_0_get_smu_metrics_data(smu, member_type, value);
}
static int smu_v14_0_0_get_dpm_level_count(struct smu_context *smu,
@ -1230,7 +1060,7 @@ static const struct pptable_funcs smu_v14_0_0_ppt_funcs = {
.read_sensor = smu_v14_0_0_read_sensor,
.is_dpm_running = smu_v14_0_0_is_dpm_running,
.set_watermarks_table = smu_v14_0_0_set_watermarks_table,
.get_gpu_metrics = smu_v14_0_0_common_get_gpu_metrics,
.get_gpu_metrics = smu_v14_0_0_get_gpu_metrics,
.get_enabled_mask = smu_cmn_get_enabled_mask,
.get_pp_feature_mask = smu_cmn_get_pp_feature_mask,
.set_driver_table_location = smu_v14_0_set_driver_table_location,

View File

@ -1004,6 +1004,9 @@ void smu_cmn_init_soft_gpu_metrics(void *table, uint8_t frev, uint8_t crev)
case METRICS_VERSION(2, 4):
structure_size = sizeof(struct gpu_metrics_v2_4);
break;
case METRICS_VERSION(3, 0):
structure_size = sizeof(struct gpu_metrics_v3_0);
break;
default:
return;
}

View File

@ -3893,7 +3893,7 @@ typedef struct _ATOM_GPIO_PIN_ASSIGNMENT
typedef struct _ATOM_GPIO_PIN_LUT
{
ATOM_COMMON_TABLE_HEADER sHeader;
ATOM_GPIO_PIN_ASSIGNMENT asGPIO_Pin[1];
ATOM_GPIO_PIN_ASSIGNMENT asGPIO_Pin[];
}ATOM_GPIO_PIN_LUT;
/****************************************************************************/
@ -4061,7 +4061,7 @@ typedef struct _ATOM_SRC_DST_TABLE_FOR_ONE_OBJECT //usSrcDstTableOffset
UCHAR ucNumberOfSrc;
USHORT usSrcObjectID[1];
UCHAR ucNumberOfDst;
USHORT usDstObjectID[1];
USHORT usDstObjectID[];
}ATOM_SRC_DST_TABLE_FOR_ONE_OBJECT;
@ -4233,7 +4233,7 @@ typedef struct _ATOM_CONNECTOR_DEVICE_TAG_RECORD
ATOM_COMMON_RECORD_HEADER sheader;
UCHAR ucNumberOfDevice;
UCHAR ucReserved;
ATOM_CONNECTOR_DEVICE_TAG asDeviceTag[1]; //This Id is same as "ATOM_DEVICE_XXX_SUPPORT", 1 is only for allocation
ATOM_CONNECTOR_DEVICE_TAG asDeviceTag[]; //This Id is same as "ATOM_DEVICE_XXX_SUPPORT", 1 is only for allocation
}ATOM_CONNECTOR_DEVICE_TAG_RECORD;
@ -4293,7 +4293,7 @@ typedef struct _ATOM_OBJECT_GPIO_CNTL_RECORD
ATOM_COMMON_RECORD_HEADER sheader;
UCHAR ucFlags; // Future expnadibility
UCHAR ucNumberOfPins; // Number of GPIO pins used to control the object
ATOM_GPIO_PIN_CONTROL_PAIR asGpio[1]; // the real gpio pin pair determined by number of pins ucNumberOfPins
ATOM_GPIO_PIN_CONTROL_PAIR asGpio[]; // the real gpio pin pair determined by number of pins ucNumberOfPins
}ATOM_OBJECT_GPIO_CNTL_RECORD;
//Definitions for GPIO pin state
@ -4444,7 +4444,7 @@ typedef struct _ATOM_BRACKET_LAYOUT_RECORD
UCHAR ucWidth;
UCHAR ucConnNum;
UCHAR ucReserved;
ATOM_CONNECTOR_LAYOUT_INFO asConnInfo[1];
ATOM_CONNECTOR_LAYOUT_INFO asConnInfo[];
}ATOM_BRACKET_LAYOUT_RECORD;
/****************************************************************************/
@ -4600,7 +4600,7 @@ typedef struct _ATOM_I2C_VOLTAGE_OBJECT_V3
UCHAR ucVoltageControlAddress;
UCHAR ucVoltageControlOffset;
ULONG ulReserved;
VOLTAGE_LUT_ENTRY asVolI2cLut[1]; // end with 0xff
VOLTAGE_LUT_ENTRY asVolI2cLut[]; // end with 0xff
}ATOM_I2C_VOLTAGE_OBJECT_V3;
// ATOM_I2C_VOLTAGE_OBJECT_V3.ucVoltageControlFlag
@ -4625,7 +4625,7 @@ typedef struct _ATOM_LEAKAGE_VOLTAGE_OBJECT_V3
UCHAR ucLeakageEntryNum; // indicate the entry number of LeakageId/Voltage Lut table
UCHAR ucReserved[2];
ULONG ulMaxVoltageLevel;
LEAKAGE_VOLTAGE_LUT_ENTRY_V2 asLeakageIdLut[1];
LEAKAGE_VOLTAGE_LUT_ENTRY_V2 asLeakageIdLut[];
}ATOM_LEAKAGE_VOLTAGE_OBJECT_V3;
@ -4753,7 +4753,7 @@ typedef struct _ATOM_POWER_SOURCE_INFO
{
ATOM_COMMON_TABLE_HEADER asHeader;
UCHAR asPwrbehave[16];
ATOM_POWER_SOURCE_OBJECT asPwrObj[1];
ATOM_POWER_SOURCE_OBJECT asPwrObj[];
}ATOM_POWER_SOURCE_INFO;
@ -5440,7 +5440,7 @@ typedef struct _ATOM_FUSION_SYSTEM_INFO_V2
typedef struct _ATOM_I2C_DATA_RECORD
{
UCHAR ucNunberOfBytes; //Indicates how many bytes SW needs to write to the external ASIC for one block, besides to "Start" and "Stop"
UCHAR ucI2CData[1]; //I2C data in bytes, should be less than 16 bytes usually
UCHAR ucI2CData[]; //I2C data in bytes, should be less than 16 bytes usually
}ATOM_I2C_DATA_RECORD;
@ -5451,14 +5451,14 @@ typedef struct _ATOM_I2C_DEVICE_SETUP_INFO
UCHAR ucSSChipID; //SS chip being used
UCHAR ucSSChipSlaveAddr; //Slave Address to set up this SS chip
UCHAR ucNumOfI2CDataRecords; //number of data block
ATOM_I2C_DATA_RECORD asI2CData[1];
ATOM_I2C_DATA_RECORD asI2CData[];
}ATOM_I2C_DEVICE_SETUP_INFO;
//==========================================================================================
typedef struct _ATOM_ASIC_MVDD_INFO
{
ATOM_COMMON_TABLE_HEADER sHeader;
ATOM_I2C_DEVICE_SETUP_INFO asI2CSetup[1];
ATOM_I2C_DEVICE_SETUP_INFO asI2CSetup[];
}ATOM_ASIC_MVDD_INFO;
//==========================================================================================
@ -5520,7 +5520,7 @@ typedef struct _ATOM_ASIC_INTERNAL_SS_INFO
typedef struct _ATOM_ASIC_INTERNAL_SS_INFO_V2
{
ATOM_COMMON_TABLE_HEADER sHeader;
ATOM_ASIC_SS_ASSIGNMENT_V2 asSpreadSpectrum[1]; //this is point only.
ATOM_ASIC_SS_ASSIGNMENT_V2 asSpreadSpectrum[]; //this is point only.
}ATOM_ASIC_INTERNAL_SS_INFO_V2;
typedef struct _ATOM_ASIC_SS_ASSIGNMENT_V3
@ -5542,7 +5542,7 @@ typedef struct _ATOM_ASIC_SS_ASSIGNMENT_V3
typedef struct _ATOM_ASIC_INTERNAL_SS_INFO_V3
{
ATOM_COMMON_TABLE_HEADER sHeader;
ATOM_ASIC_SS_ASSIGNMENT_V3 asSpreadSpectrum[1]; //this is pointer only.
ATOM_ASIC_SS_ASSIGNMENT_V3 asSpreadSpectrum[]; //this is pointer only.
}ATOM_ASIC_INTERNAL_SS_INFO_V3;
@ -6282,7 +6282,7 @@ typedef union _ATOM_MEMORY_SETTING_ID_CONFIG_ACCESS
typedef struct _ATOM_MEMORY_SETTING_DATA_BLOCK{
ATOM_MEMORY_SETTING_ID_CONFIG_ACCESS ulMemoryID;
ULONG aulMemData[1];
ULONG aulMemData[];
}ATOM_MEMORY_SETTING_DATA_BLOCK;
@ -7092,7 +7092,7 @@ typedef struct _ATOM_DISP_OUT_INFO_V3
UCHAR ucCoreRefClkSource; // value of CORE_REF_CLK_SOURCE
UCHAR ucDispCaps;
UCHAR ucReserved[2];
ASIC_TRANSMITTER_INFO_V2 asTransmitterInfo[1]; // for alligment only
ASIC_TRANSMITTER_INFO_V2 asTransmitterInfo[]; // for alligment only
}ATOM_DISP_OUT_INFO_V3;
//ucDispCaps
@ -7324,12 +7324,12 @@ typedef struct _CLOCK_CONDITION_SETTING_ENTRY{
USHORT usMaxClockFreq;
UCHAR ucEncodeMode;
UCHAR ucPhySel;
ULONG ulAnalogSetting[1];
ULONG ulAnalogSetting[];
}CLOCK_CONDITION_SETTING_ENTRY;
typedef struct _CLOCK_CONDITION_SETTING_INFO{
USHORT usEntrySize;
CLOCK_CONDITION_SETTING_ENTRY asClkCondSettingEntry[1];
CLOCK_CONDITION_SETTING_ENTRY asClkCondSettingEntry[];
}CLOCK_CONDITION_SETTING_INFO;
typedef struct _PHY_CONDITION_REG_VAL{
@ -7346,27 +7346,27 @@ typedef struct _PHY_CONDITION_REG_VAL_V2{
typedef struct _PHY_CONDITION_REG_INFO{
USHORT usRegIndex;
USHORT usSize;
PHY_CONDITION_REG_VAL asRegVal[1];
PHY_CONDITION_REG_VAL asRegVal[];
}PHY_CONDITION_REG_INFO;
typedef struct _PHY_CONDITION_REG_INFO_V2{
USHORT usRegIndex;
USHORT usSize;
PHY_CONDITION_REG_VAL_V2 asRegVal[1];
PHY_CONDITION_REG_VAL_V2 asRegVal[];
}PHY_CONDITION_REG_INFO_V2;
typedef struct _PHY_ANALOG_SETTING_INFO{
UCHAR ucEncodeMode;
UCHAR ucPhySel;
USHORT usSize;
PHY_CONDITION_REG_INFO asAnalogSetting[1];
PHY_CONDITION_REG_INFO asAnalogSetting[];
}PHY_ANALOG_SETTING_INFO;
typedef struct _PHY_ANALOG_SETTING_INFO_V2{
UCHAR ucEncodeMode;
UCHAR ucPhySel;
USHORT usSize;
PHY_CONDITION_REG_INFO_V2 asAnalogSetting[1];
PHY_CONDITION_REG_INFO_V2 asAnalogSetting[];
}PHY_ANALOG_SETTING_INFO_V2;
typedef struct _GFX_HAVESTING_PARAMETERS {

View File

@ -1,11 +1,12 @@
# SPDX-License-Identifier: GPL-2.0
config DRM_SHMOBILE
tristate "DRM Support for SH Mobile"
depends on DRM
depends on DRM && PM
depends on ARCH_RENESAS || ARCH_SHMOBILE || COMPILE_TEST
select BACKLIGHT_CLASS_DEVICE
select DRM_KMS_HELPER
select DRM_GEM_DMA_HELPER
select VIDEOMODE_HELPERS
help
Choose this option if you have an SH Mobile chipset.
If M is selected the module will be called shmob-drm.

View File

@ -1,6 +1,5 @@
# SPDX-License-Identifier: GPL-2.0
shmob-drm-y := shmob_drm_backlight.o \
shmob_drm_crtc.o \
shmob-drm-y := shmob_drm_crtc.o \
shmob_drm_drv.o \
shmob_drm_kms.o \
shmob_drm_plane.o

View File

@ -1,82 +0,0 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* shmob_drm_backlight.c -- SH Mobile DRM Backlight
*
* Copyright (C) 2012 Renesas Electronics Corporation
*
* Laurent Pinchart (laurent.pinchart@ideasonboard.com)
*/
#include <linux/backlight.h>
#include "shmob_drm_backlight.h"
#include "shmob_drm_crtc.h"
#include "shmob_drm_drv.h"
static int shmob_drm_backlight_update(struct backlight_device *bdev)
{
struct shmob_drm_connector *scon = bl_get_data(bdev);
struct shmob_drm_device *sdev = scon->connector.dev->dev_private;
const struct shmob_drm_backlight_data *bdata = &sdev->pdata->backlight;
int brightness = backlight_get_brightness(bdev);
return bdata->set_brightness(brightness);
}
static int shmob_drm_backlight_get_brightness(struct backlight_device *bdev)
{
struct shmob_drm_connector *scon = bl_get_data(bdev);
struct shmob_drm_device *sdev = scon->connector.dev->dev_private;
const struct shmob_drm_backlight_data *bdata = &sdev->pdata->backlight;
return bdata->get_brightness();
}
static const struct backlight_ops shmob_drm_backlight_ops = {
.options = BL_CORE_SUSPENDRESUME,
.update_status = shmob_drm_backlight_update,
.get_brightness = shmob_drm_backlight_get_brightness,
};
void shmob_drm_backlight_dpms(struct shmob_drm_connector *scon, int mode)
{
if (scon->backlight == NULL)
return;
scon->backlight->props.power = mode == DRM_MODE_DPMS_ON
? FB_BLANK_UNBLANK : FB_BLANK_POWERDOWN;
backlight_update_status(scon->backlight);
}
int shmob_drm_backlight_init(struct shmob_drm_connector *scon)
{
struct shmob_drm_device *sdev = scon->connector.dev->dev_private;
const struct shmob_drm_backlight_data *bdata = &sdev->pdata->backlight;
struct drm_connector *connector = &scon->connector;
struct drm_device *dev = connector->dev;
struct backlight_device *backlight;
if (!bdata->max_brightness)
return 0;
backlight = backlight_device_register(bdata->name, dev->dev, scon,
&shmob_drm_backlight_ops, NULL);
if (IS_ERR(backlight)) {
dev_err(dev->dev, "unable to register backlight device: %ld\n",
PTR_ERR(backlight));
return PTR_ERR(backlight);
}
backlight->props.max_brightness = bdata->max_brightness;
backlight->props.brightness = bdata->max_brightness;
backlight->props.power = FB_BLANK_POWERDOWN;
backlight_update_status(backlight);
scon->backlight = backlight;
return 0;
}
void shmob_drm_backlight_exit(struct shmob_drm_connector *scon)
{
backlight_device_unregister(scon->backlight);
}

View File

@ -1,19 +0,0 @@
/* SPDX-License-Identifier: GPL-2.0+ */
/*
* shmob_drm_backlight.h -- SH Mobile DRM Backlight
*
* Copyright (C) 2012 Renesas Electronics Corporation
*
* Laurent Pinchart (laurent.pinchart@ideasonboard.com)
*/
#ifndef __SHMOB_DRM_BACKLIGHT_H__
#define __SHMOB_DRM_BACKLIGHT_H__
struct shmob_drm_connector;
void shmob_drm_backlight_dpms(struct shmob_drm_connector *scon, int mode);
int shmob_drm_backlight_init(struct shmob_drm_connector *scon);
void shmob_drm_backlight_exit(struct shmob_drm_connector *scon);
#endif /* __SHMOB_DRM_BACKLIGHT_H__ */

View File

@ -7,9 +7,18 @@
* Laurent Pinchart (laurent.pinchart@ideasonboard.com)
*/
#include <linux/backlight.h>
#include <linux/clk.h>
#include <linux/media-bus-format.h>
#include <linux/of.h>
#include <linux/of_graph.h>
#include <linux/pm_runtime.h>
#include <drm/drm_atomic.h>
#include <drm/drm_atomic_helper.h>
#include <drm/drm_atomic_state_helper.h>
#include <drm/drm_atomic_uapi.h>
#include <drm/drm_bridge.h>
#include <drm/drm_bridge_connector.h>
#include <drm/drm_crtc.h>
#include <drm/drm_crtc_helper.h>
#include <drm/drm_fb_dma_helper.h>
@ -18,85 +27,123 @@
#include <drm/drm_gem_dma_helper.h>
#include <drm/drm_modeset_helper.h>
#include <drm/drm_modeset_helper_vtables.h>
#include <drm/drm_plane_helper.h>
#include <drm/drm_panel.h>
#include <drm/drm_probe_helper.h>
#include <drm/drm_simple_kms_helper.h>
#include <drm/drm_vblank.h>
#include "shmob_drm_backlight.h"
#include <video/videomode.h>
#include "shmob_drm_crtc.h"
#include "shmob_drm_drv.h"
#include "shmob_drm_kms.h"
#include "shmob_drm_plane.h"
#include "shmob_drm_regs.h"
/*
* TODO: panel support
*/
/* -----------------------------------------------------------------------------
* Clock management
* Page Flip
*/
static int shmob_drm_clk_on(struct shmob_drm_device *sdev)
void shmob_drm_crtc_finish_page_flip(struct shmob_drm_crtc *scrtc)
{
int ret;
struct drm_pending_vblank_event *event;
struct drm_device *dev = scrtc->base.dev;
unsigned long flags;
if (sdev->clock) {
ret = clk_prepare_enable(sdev->clock);
if (ret < 0)
return ret;
spin_lock_irqsave(&dev->event_lock, flags);
event = scrtc->event;
scrtc->event = NULL;
if (event) {
drm_crtc_send_vblank_event(&scrtc->base, event);
wake_up(&scrtc->flip_wait);
drm_crtc_vblank_put(&scrtc->base);
}
return 0;
spin_unlock_irqrestore(&dev->event_lock, flags);
}
static void shmob_drm_clk_off(struct shmob_drm_device *sdev)
static bool shmob_drm_crtc_page_flip_pending(struct shmob_drm_crtc *scrtc)
{
if (sdev->clock)
clk_disable_unprepare(sdev->clock);
struct drm_device *dev = scrtc->base.dev;
unsigned long flags;
bool pending;
spin_lock_irqsave(&dev->event_lock, flags);
pending = scrtc->event != NULL;
spin_unlock_irqrestore(&dev->event_lock, flags);
return pending;
}
static void shmob_drm_crtc_wait_page_flip(struct shmob_drm_crtc *scrtc)
{
struct drm_crtc *crtc = &scrtc->base;
struct shmob_drm_device *sdev = to_shmob_device(crtc->dev);
if (wait_event_timeout(scrtc->flip_wait,
!shmob_drm_crtc_page_flip_pending(scrtc),
msecs_to_jiffies(50)))
return;
dev_warn(sdev->dev, "page flip timeout\n");
shmob_drm_crtc_finish_page_flip(scrtc);
}
/* -----------------------------------------------------------------------------
* CRTC
*/
static const struct {
u32 fmt;
u32 ldmt1r;
} shmob_drm_bus_fmts[] = {
{ MEDIA_BUS_FMT_RGB888_3X8, LDMT1R_MIFTYP_RGB8 },
{ MEDIA_BUS_FMT_RGB666_2X9_BE, LDMT1R_MIFTYP_RGB9 },
{ MEDIA_BUS_FMT_RGB888_2X12_BE, LDMT1R_MIFTYP_RGB12A },
{ MEDIA_BUS_FMT_RGB444_1X12, LDMT1R_MIFTYP_RGB12B },
{ MEDIA_BUS_FMT_RGB565_1X16, LDMT1R_MIFTYP_RGB16 },
{ MEDIA_BUS_FMT_RGB666_1X18, LDMT1R_MIFTYP_RGB18 },
{ MEDIA_BUS_FMT_RGB888_1X24, LDMT1R_MIFTYP_RGB24 },
{ MEDIA_BUS_FMT_UYVY8_1X16, LDMT1R_MIFTYP_YCBCR },
};
static void shmob_drm_crtc_setup_geometry(struct shmob_drm_crtc *scrtc)
{
struct drm_crtc *crtc = &scrtc->crtc;
struct shmob_drm_device *sdev = crtc->dev->dev_private;
const struct shmob_drm_interface_data *idata = &sdev->pdata->iface;
struct drm_crtc *crtc = &scrtc->base;
struct shmob_drm_device *sdev = to_shmob_device(crtc->dev);
const struct drm_display_info *info = &sdev->connector->display_info;
const struct drm_display_mode *mode = &crtc->mode;
unsigned int i;
u32 value;
value = sdev->ldmt1r
| ((mode->flags & DRM_MODE_FLAG_PVSYNC) ? 0 : LDMT1R_VPOL)
| ((mode->flags & DRM_MODE_FLAG_PHSYNC) ? 0 : LDMT1R_HPOL)
| ((idata->flags & SHMOB_DRM_IFACE_FL_DWPOL) ? LDMT1R_DWPOL : 0)
| ((idata->flags & SHMOB_DRM_IFACE_FL_DIPOL) ? LDMT1R_DIPOL : 0)
| ((idata->flags & SHMOB_DRM_IFACE_FL_DAPOL) ? LDMT1R_DAPOL : 0)
| ((idata->flags & SHMOB_DRM_IFACE_FL_HSCNT) ? LDMT1R_HSCNT : 0)
| ((idata->flags & SHMOB_DRM_IFACE_FL_DWCNT) ? LDMT1R_DWCNT : 0);
lcdc_write(sdev, LDMT1R, value);
if (idata->interface >= SHMOB_DRM_IFACE_SYS8A &&
idata->interface <= SHMOB_DRM_IFACE_SYS24) {
/* Setup SYS bus. */
value = (idata->sys.cs_setup << LDMT2R_CSUP_SHIFT)
| (idata->sys.vsync_active_high ? LDMT2R_RSV : 0)
| (idata->sys.vsync_dir_input ? LDMT2R_VSEL : 0)
| (idata->sys.write_setup << LDMT2R_WCSC_SHIFT)
| (idata->sys.write_cycle << LDMT2R_WCEC_SHIFT)
| (idata->sys.write_strobe << LDMT2R_WCLW_SHIFT);
lcdc_write(sdev, LDMT2R, value);
value = (idata->sys.read_latch << LDMT3R_RDLC_SHIFT)
| (idata->sys.read_setup << LDMT3R_RCSC_SHIFT)
| (idata->sys.read_cycle << LDMT3R_RCEC_SHIFT)
| (idata->sys.read_strobe << LDMT3R_RCLW_SHIFT);
lcdc_write(sdev, LDMT3R, value);
if (!info->num_bus_formats || !info->bus_formats) {
dev_warn(sdev->dev, "No bus format reported, using RGB888\n");
value = LDMT1R_MIFTYP_RGB24;
} else {
for (i = 0; i < ARRAY_SIZE(shmob_drm_bus_fmts); i++) {
if (shmob_drm_bus_fmts[i].fmt == info->bus_formats[0])
break;
}
if (i < ARRAY_SIZE(shmob_drm_bus_fmts)) {
value = shmob_drm_bus_fmts[i].ldmt1r;
} else {
dev_warn(sdev->dev,
"unsupported bus format 0x%x, using RGB888\n",
info->bus_formats[0]);
value = LDMT1R_MIFTYP_RGB24;
}
}
if (info->bus_flags & DRM_BUS_FLAG_PIXDATA_DRIVE_POSEDGE)
value |= LDMT1R_DWPOL;
if (info->bus_flags & DRM_BUS_FLAG_DE_LOW)
value |= LDMT1R_DIPOL;
if (mode->flags & DRM_MODE_FLAG_NVSYNC)
value |= LDMT1R_VPOL;
if (mode->flags & DRM_MODE_FLAG_NHSYNC)
value |= LDMT1R_HPOL;
lcdc_write(sdev, LDMT1R, value);
value = ((mode->hdisplay / 8) << 16) /* HDCN */
| (mode->htotal / 8); /* HTCN */
lcdc_write(sdev, LDHCNR, value);
@ -121,7 +168,7 @@ static void shmob_drm_crtc_setup_geometry(struct shmob_drm_crtc *scrtc)
static void shmob_drm_crtc_start_stop(struct shmob_drm_crtc *scrtc, bool start)
{
struct shmob_drm_device *sdev = scrtc->crtc.dev->dev_private;
struct shmob_drm_device *sdev = to_shmob_device(scrtc->base.dev);
u32 value;
value = lcdc_read(sdev, LDCNT2R);
@ -145,34 +192,23 @@ static void shmob_drm_crtc_start_stop(struct shmob_drm_crtc *scrtc, bool start)
}
}
/*
* shmob_drm_crtc_start - Configure and start the LCDC
* @scrtc: the SH Mobile CRTC
*
* Configure and start the LCDC device. External devices (clocks, MERAM, panels,
* ...) are not touched by this function.
*/
static void shmob_drm_crtc_start(struct shmob_drm_crtc *scrtc)
static inline struct shmob_drm_crtc *to_shmob_crtc(struct drm_crtc *crtc)
{
struct drm_crtc *crtc = &scrtc->crtc;
struct shmob_drm_device *sdev = crtc->dev->dev_private;
const struct shmob_drm_interface_data *idata = &sdev->pdata->iface;
const struct shmob_drm_format_info *format;
struct drm_device *dev = sdev->ddev;
struct drm_plane *plane;
return container_of(crtc, struct shmob_drm_crtc, base);
}
static void shmob_drm_crtc_atomic_enable(struct drm_crtc *crtc,
struct drm_atomic_state *state)
{
struct shmob_drm_crtc *scrtc = to_shmob_crtc(crtc);
struct shmob_drm_device *sdev = to_shmob_device(crtc->dev);
unsigned int clk_div = sdev->config.clk_div;
struct device *dev = sdev->dev;
u32 value;
int ret;
if (scrtc->started)
return;
format = shmob_drm_format_info(crtc->primary->fb->format->format);
if (WARN_ON(format == NULL))
return;
/* Enable clocks before accessing the hardware. */
ret = shmob_drm_clk_on(sdev);
if (ret < 0)
ret = pm_runtime_resume_and_get(dev);
if (ret)
return;
/* Reset and enable the LCDC. */
@ -188,79 +224,50 @@ static void shmob_drm_crtc_start(struct shmob_drm_crtc *scrtc)
lcdc_write(sdev, LDPMR, 0);
value = sdev->lddckr;
if (idata->clk_div) {
if (clk_div) {
/* FIXME: sh7724 can only use 42, 48, 54 and 60 for the divider
* denominator.
*/
lcdc_write(sdev, LDDCKPAT1R, 0);
lcdc_write(sdev, LDDCKPAT2R, (1 << (idata->clk_div / 2)) - 1);
lcdc_write(sdev, LDDCKPAT2R, (1 << (clk_div / 2)) - 1);
if (idata->clk_div == 1)
if (clk_div == 1)
value |= LDDCKR_MOSEL;
else
value |= idata->clk_div;
value |= clk_div;
}
lcdc_write(sdev, LDDCKR, value);
lcdc_write(sdev, LDDCKSTPR, 0);
lcdc_wait_bit(sdev, LDDCKSTPR, ~0, 0);
/* TODO: Setup SYS panel */
/* Setup geometry, format, frame buffer memory and operation mode. */
shmob_drm_crtc_setup_geometry(scrtc);
/* TODO: Handle YUV colorspaces. Hardcode REC709 for now. */
lcdc_write(sdev, LDDFR, format->lddfr | LDDFR_CF1);
lcdc_write(sdev, LDMLSR, scrtc->line_size);
lcdc_write(sdev, LDSA1R, scrtc->dma[0]);
if (format->yuv)
lcdc_write(sdev, LDSA2R, scrtc->dma[1]);
lcdc_write(sdev, LDSM1R, 0);
/* Word and long word swap. */
switch (format->fourcc) {
case DRM_FORMAT_RGB565:
case DRM_FORMAT_NV21:
case DRM_FORMAT_NV61:
case DRM_FORMAT_NV42:
value = LDDDSR_LS | LDDDSR_WS;
break;
case DRM_FORMAT_RGB888:
case DRM_FORMAT_NV12:
case DRM_FORMAT_NV16:
case DRM_FORMAT_NV24:
value = LDDDSR_LS | LDDDSR_WS | LDDDSR_BS;
break;
case DRM_FORMAT_ARGB8888:
case DRM_FORMAT_XRGB8888:
default:
value = LDDDSR_LS;
break;
}
lcdc_write(sdev, LDDDSR, value);
/* Setup planes. */
drm_for_each_legacy_plane(plane, dev) {
if (plane->crtc == crtc)
shmob_drm_plane_setup(plane);
}
/* Enable the display output. */
lcdc_write(sdev, LDCNT1R, LDCNT1R_DE);
shmob_drm_crtc_start_stop(scrtc, true);
scrtc->started = true;
/* Turn vertical blank interrupt reporting back on. */
drm_crtc_vblank_on(crtc);
}
static void shmob_drm_crtc_stop(struct shmob_drm_crtc *scrtc)
static void shmob_drm_crtc_atomic_disable(struct drm_crtc *crtc,
struct drm_atomic_state *state)
{
struct drm_crtc *crtc = &scrtc->crtc;
struct shmob_drm_device *sdev = crtc->dev->dev_private;
struct shmob_drm_crtc *scrtc = to_shmob_crtc(crtc);
struct shmob_drm_device *sdev = to_shmob_device(crtc->dev);
if (!scrtc->started)
return;
/*
* Disable vertical blank interrupt reporting. We first need to wait
* for page flip completion before stopping the CRTC as userspace
* expects page flips to eventually complete.
*/
shmob_drm_crtc_wait_page_flip(scrtc);
drm_crtc_vblank_off(crtc);
/* Stop the LCDC. */
shmob_drm_crtc_start_stop(scrtc, false);
@ -268,145 +275,31 @@ static void shmob_drm_crtc_stop(struct shmob_drm_crtc *scrtc)
/* Disable the display output. */
lcdc_write(sdev, LDCNT1R, 0);
/* Stop clocks. */
shmob_drm_clk_off(sdev);
scrtc->started = false;
pm_runtime_put(sdev->dev);
}
void shmob_drm_crtc_suspend(struct shmob_drm_crtc *scrtc)
static void shmob_drm_crtc_atomic_flush(struct drm_crtc *crtc,
struct drm_atomic_state *state)
{
shmob_drm_crtc_stop(scrtc);
}
struct drm_pending_vblank_event *event;
struct drm_device *dev = crtc->dev;
unsigned long flags;
void shmob_drm_crtc_resume(struct shmob_drm_crtc *scrtc)
{
if (scrtc->dpms != DRM_MODE_DPMS_ON)
return;
shmob_drm_crtc_start(scrtc);
}
static void shmob_drm_crtc_compute_base(struct shmob_drm_crtc *scrtc,
int x, int y)
{
struct drm_crtc *crtc = &scrtc->crtc;
struct drm_framebuffer *fb = crtc->primary->fb;
struct drm_gem_dma_object *gem;
unsigned int bpp;
bpp = scrtc->format->yuv ? 8 : scrtc->format->bpp;
gem = drm_fb_dma_get_gem_obj(fb, 0);
scrtc->dma[0] = gem->dma_addr + fb->offsets[0]
+ y * fb->pitches[0] + x * bpp / 8;
if (scrtc->format->yuv) {
bpp = scrtc->format->bpp - 8;
gem = drm_fb_dma_get_gem_obj(fb, 1);
scrtc->dma[1] = gem->dma_addr + fb->offsets[1]
+ y / (bpp == 4 ? 2 : 1) * fb->pitches[1]
+ x * (bpp == 16 ? 2 : 1);
if (crtc->state->event) {
spin_lock_irqsave(&dev->event_lock, flags);
event = crtc->state->event;
crtc->state->event = NULL;
drm_crtc_send_vblank_event(crtc, event);
spin_unlock_irqrestore(&dev->event_lock, flags);
}
}
static void shmob_drm_crtc_update_base(struct shmob_drm_crtc *scrtc)
{
struct drm_crtc *crtc = &scrtc->crtc;
struct shmob_drm_device *sdev = crtc->dev->dev_private;
shmob_drm_crtc_compute_base(scrtc, crtc->x, crtc->y);
lcdc_write_mirror(sdev, LDSA1R, scrtc->dma[0]);
if (scrtc->format->yuv)
lcdc_write_mirror(sdev, LDSA2R, scrtc->dma[1]);
lcdc_write(sdev, LDRCNTR, lcdc_read(sdev, LDRCNTR) ^ LDRCNTR_MRS);
}
#define to_shmob_crtc(c) container_of(c, struct shmob_drm_crtc, crtc)
static void shmob_drm_crtc_dpms(struct drm_crtc *crtc, int mode)
{
struct shmob_drm_crtc *scrtc = to_shmob_crtc(crtc);
if (scrtc->dpms == mode)
return;
if (mode == DRM_MODE_DPMS_ON)
shmob_drm_crtc_start(scrtc);
else
shmob_drm_crtc_stop(scrtc);
scrtc->dpms = mode;
}
static void shmob_drm_crtc_mode_prepare(struct drm_crtc *crtc)
{
shmob_drm_crtc_dpms(crtc, DRM_MODE_DPMS_OFF);
}
static int shmob_drm_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 shmob_drm_crtc *scrtc = to_shmob_crtc(crtc);
struct shmob_drm_device *sdev = crtc->dev->dev_private;
const struct shmob_drm_format_info *format;
format = shmob_drm_format_info(crtc->primary->fb->format->format);
if (format == NULL) {
dev_dbg(sdev->dev, "mode_set: unsupported format %p4cc\n",
&crtc->primary->fb->format->format);
return -EINVAL;
}
scrtc->format = format;
scrtc->line_size = crtc->primary->fb->pitches[0];
shmob_drm_crtc_compute_base(scrtc, x, y);
return 0;
}
static void shmob_drm_crtc_mode_commit(struct drm_crtc *crtc)
{
shmob_drm_crtc_dpms(crtc, DRM_MODE_DPMS_ON);
}
static int shmob_drm_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y,
struct drm_framebuffer *old_fb)
{
shmob_drm_crtc_update_base(to_shmob_crtc(crtc));
return 0;
}
static const struct drm_crtc_helper_funcs crtc_helper_funcs = {
.dpms = shmob_drm_crtc_dpms,
.prepare = shmob_drm_crtc_mode_prepare,
.commit = shmob_drm_crtc_mode_commit,
.mode_set = shmob_drm_crtc_mode_set,
.mode_set_base = shmob_drm_crtc_mode_set_base,
.atomic_flush = shmob_drm_crtc_atomic_flush,
.atomic_enable = shmob_drm_crtc_atomic_enable,
.atomic_disable = shmob_drm_crtc_atomic_disable,
};
void shmob_drm_crtc_finish_page_flip(struct shmob_drm_crtc *scrtc)
{
struct drm_pending_vblank_event *event;
struct drm_device *dev = scrtc->crtc.dev;
unsigned long flags;
spin_lock_irqsave(&dev->event_lock, flags);
event = scrtc->event;
scrtc->event = NULL;
if (event) {
drm_crtc_send_vblank_event(&scrtc->crtc, event);
drm_crtc_vblank_put(&scrtc->crtc);
}
spin_unlock_irqrestore(&dev->event_lock, flags);
}
static int shmob_drm_crtc_page_flip(struct drm_crtc *crtc,
struct drm_framebuffer *fb,
struct drm_pending_vblank_event *event,
@ -414,7 +307,7 @@ static int shmob_drm_crtc_page_flip(struct drm_crtc *crtc,
struct drm_modeset_acquire_ctx *ctx)
{
struct shmob_drm_crtc *scrtc = to_shmob_crtc(crtc);
struct drm_device *dev = scrtc->crtc.dev;
struct drm_device *dev = scrtc->base.dev;
unsigned long flags;
spin_lock_irqsave(&dev->event_lock, flags);
@ -424,12 +317,11 @@ static int shmob_drm_crtc_page_flip(struct drm_crtc *crtc,
}
spin_unlock_irqrestore(&dev->event_lock, flags);
crtc->primary->fb = fb;
shmob_drm_crtc_update_base(scrtc);
drm_atomic_set_fb_for_plane(crtc->primary->state, fb);
if (event) {
event->pipe = 0;
drm_crtc_vblank_get(&scrtc->crtc);
drm_crtc_vblank_get(&scrtc->base);
spin_lock_irqsave(&dev->event_lock, flags);
scrtc->event = event;
spin_unlock_irqrestore(&dev->event_lock, flags);
@ -457,7 +349,7 @@ static void shmob_drm_crtc_enable_vblank(struct shmob_drm_device *sdev,
static int shmob_drm_enable_vblank(struct drm_crtc *crtc)
{
struct shmob_drm_device *sdev = crtc->dev->dev_private;
struct shmob_drm_device *sdev = to_shmob_device(crtc->dev);
shmob_drm_crtc_enable_vblank(sdev, true);
@ -466,88 +358,65 @@ static int shmob_drm_enable_vblank(struct drm_crtc *crtc)
static void shmob_drm_disable_vblank(struct drm_crtc *crtc)
{
struct shmob_drm_device *sdev = crtc->dev->dev_private;
struct shmob_drm_device *sdev = to_shmob_device(crtc->dev);
shmob_drm_crtc_enable_vblank(sdev, false);
}
static const struct drm_crtc_funcs crtc_funcs = {
.reset = drm_atomic_helper_crtc_reset,
.destroy = drm_crtc_cleanup,
.set_config = drm_crtc_helper_set_config,
.set_config = drm_atomic_helper_set_config,
.page_flip = shmob_drm_crtc_page_flip,
.atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state,
.atomic_destroy_state = drm_atomic_helper_crtc_destroy_state,
.enable_vblank = shmob_drm_enable_vblank,
.disable_vblank = shmob_drm_disable_vblank,
};
static const uint32_t modeset_formats[] = {
DRM_FORMAT_RGB565,
DRM_FORMAT_RGB888,
DRM_FORMAT_ARGB8888,
DRM_FORMAT_XRGB8888,
};
static const struct drm_plane_funcs primary_plane_funcs = {
DRM_PLANE_NON_ATOMIC_FUNCS,
};
int shmob_drm_crtc_create(struct shmob_drm_device *sdev)
{
struct drm_crtc *crtc = &sdev->crtc.crtc;
struct drm_plane *primary;
struct drm_crtc *crtc = &sdev->crtc.base;
struct drm_plane *primary, *plane;
unsigned int i;
int ret;
sdev->crtc.dpms = DRM_MODE_DPMS_OFF;
init_waitqueue_head(&sdev->crtc.flip_wait);
primary = __drm_universal_plane_alloc(sdev->ddev, sizeof(*primary), 0,
0, &primary_plane_funcs,
modeset_formats,
ARRAY_SIZE(modeset_formats),
NULL, DRM_PLANE_TYPE_PRIMARY,
NULL);
primary = shmob_drm_plane_create(sdev, DRM_PLANE_TYPE_PRIMARY, 0);
if (IS_ERR(primary))
return PTR_ERR(primary);
ret = drm_crtc_init_with_planes(sdev->ddev, crtc, primary, NULL,
&crtc_funcs, NULL);
if (ret < 0) {
drm_plane_cleanup(primary);
kfree(primary);
return ret;
for (i = 1; i < 5; ++i) {
plane = shmob_drm_plane_create(sdev, DRM_PLANE_TYPE_OVERLAY, i);
if (IS_ERR(plane))
return PTR_ERR(plane);
}
ret = drm_crtc_init_with_planes(&sdev->ddev, crtc, primary, NULL,
&crtc_funcs, NULL);
if (ret < 0)
return ret;
drm_crtc_helper_add(crtc, &crtc_helper_funcs);
/* Start with vertical blank interrupt reporting disabled. */
drm_crtc_vblank_off(crtc);
return 0;
}
/* -----------------------------------------------------------------------------
* Encoder
* Legacy Encoder
*/
#define to_shmob_encoder(e) \
container_of(e, struct shmob_drm_encoder, encoder)
static void shmob_drm_encoder_dpms(struct drm_encoder *encoder, int mode)
{
struct shmob_drm_encoder *senc = to_shmob_encoder(encoder);
struct shmob_drm_device *sdev = encoder->dev->dev_private;
struct shmob_drm_connector *scon = &sdev->connector;
if (senc->dpms == mode)
return;
shmob_drm_backlight_dpms(scon, mode);
senc->dpms = mode;
}
static bool shmob_drm_encoder_mode_fixup(struct drm_encoder *encoder,
const struct drm_display_mode *mode,
struct drm_display_mode *adjusted_mode)
{
struct drm_device *dev = encoder->dev;
struct shmob_drm_device *sdev = dev->dev_private;
struct drm_connector *connector = &sdev->connector.connector;
struct shmob_drm_device *sdev = to_shmob_device(dev);
struct drm_connector *connector = sdev->connector;
const struct drm_display_mode *panel_mode;
if (list_empty(&connector->modes)) {
@ -563,60 +432,61 @@ static bool shmob_drm_encoder_mode_fixup(struct drm_encoder *encoder,
return true;
}
static void shmob_drm_encoder_mode_prepare(struct drm_encoder *encoder)
{
/* No-op, everything is handled in the CRTC code. */
}
static void shmob_drm_encoder_mode_set(struct drm_encoder *encoder,
struct drm_display_mode *mode,
struct drm_display_mode *adjusted_mode)
{
/* No-op, everything is handled in the CRTC code. */
}
static void shmob_drm_encoder_mode_commit(struct drm_encoder *encoder)
{
/* No-op, everything is handled in the CRTC code. */
}
static const struct drm_encoder_helper_funcs encoder_helper_funcs = {
.dpms = shmob_drm_encoder_dpms,
.mode_fixup = shmob_drm_encoder_mode_fixup,
.prepare = shmob_drm_encoder_mode_prepare,
.commit = shmob_drm_encoder_mode_commit,
.mode_set = shmob_drm_encoder_mode_set,
};
/* -----------------------------------------------------------------------------
* Encoder
*/
int shmob_drm_encoder_create(struct shmob_drm_device *sdev)
{
struct drm_encoder *encoder = &sdev->encoder.encoder;
struct drm_encoder *encoder = &sdev->encoder;
struct drm_bridge *bridge;
int ret;
sdev->encoder.dpms = DRM_MODE_DPMS_OFF;
encoder->possible_crtcs = 1;
ret = drm_simple_encoder_init(sdev->ddev, encoder,
DRM_MODE_ENCODER_LVDS);
ret = drm_simple_encoder_init(&sdev->ddev, encoder,
DRM_MODE_ENCODER_DPI);
if (ret < 0)
return ret;
drm_encoder_helper_add(encoder, &encoder_helper_funcs);
if (sdev->pdata) {
drm_encoder_helper_add(encoder, &encoder_helper_funcs);
return 0;
}
/* Create a panel bridge */
bridge = devm_drm_of_get_bridge(sdev->dev, sdev->dev->of_node, 0, 0);
if (IS_ERR(bridge))
return PTR_ERR(bridge);
/* Attach the bridge to the encoder */
ret = drm_bridge_attach(encoder, bridge, NULL,
DRM_BRIDGE_ATTACH_NO_CONNECTOR);
if (ret) {
dev_err(sdev->dev, "failed to attach bridge: %pe\n",
ERR_PTR(ret));
return ret;
}
return 0;
}
/* -----------------------------------------------------------------------------
* Connector
* Legacy Connector
*/
#define to_shmob_connector(c) \
container_of(c, struct shmob_drm_connector, connector)
static inline struct shmob_drm_connector *to_shmob_connector(struct drm_connector *connector)
{
return container_of(connector, struct shmob_drm_connector, base);
}
static int shmob_drm_connector_get_modes(struct drm_connector *connector)
{
struct shmob_drm_device *sdev = connector->dev->dev_private;
struct shmob_drm_connector *scon = to_shmob_connector(connector);
struct drm_display_mode *mode;
mode = drm_mode_create(connector->dev);
@ -624,23 +494,11 @@ static int shmob_drm_connector_get_modes(struct drm_connector *connector)
return 0;
mode->type = DRM_MODE_TYPE_PREFERRED | DRM_MODE_TYPE_DRIVER;
mode->clock = sdev->pdata->panel.mode.clock;
mode->hdisplay = sdev->pdata->panel.mode.hdisplay;
mode->hsync_start = sdev->pdata->panel.mode.hsync_start;
mode->hsync_end = sdev->pdata->panel.mode.hsync_end;
mode->htotal = sdev->pdata->panel.mode.htotal;
mode->vdisplay = sdev->pdata->panel.mode.vdisplay;
mode->vsync_start = sdev->pdata->panel.mode.vsync_start;
mode->vsync_end = sdev->pdata->panel.mode.vsync_end;
mode->vtotal = sdev->pdata->panel.mode.vtotal;
mode->flags = sdev->pdata->panel.mode.flags;
drm_mode_set_name(mode);
drm_display_mode_from_videomode(scon->mode, mode);
drm_mode_probed_add(connector, mode);
connector->display_info.width_mm = sdev->pdata->panel.width_mm;
connector->display_info.height_mm = sdev->pdata->panel.height_mm;
return 1;
}
@ -659,54 +517,106 @@ static const struct drm_connector_helper_funcs connector_helper_funcs = {
static void shmob_drm_connector_destroy(struct drm_connector *connector)
{
struct shmob_drm_connector *scon = to_shmob_connector(connector);
shmob_drm_backlight_exit(scon);
drm_connector_unregister(connector);
drm_connector_cleanup(connector);
kfree(connector);
}
static const struct drm_connector_funcs connector_funcs = {
.dpms = drm_helper_connector_dpms,
.reset = drm_atomic_helper_connector_reset,
.fill_modes = drm_helper_probe_single_connector_modes,
.destroy = shmob_drm_connector_destroy,
.atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
};
static struct drm_connector *
shmob_drm_connector_init(struct shmob_drm_device *sdev,
struct drm_encoder *encoder)
{
u32 bus_fmt = sdev->pdata->iface.bus_fmt;
struct shmob_drm_connector *scon;
struct drm_connector *connector;
struct drm_display_info *info;
unsigned int i;
int ret;
for (i = 0; i < ARRAY_SIZE(shmob_drm_bus_fmts); i++) {
if (shmob_drm_bus_fmts[i].fmt == bus_fmt)
break;
}
if (i == ARRAY_SIZE(shmob_drm_bus_fmts)) {
dev_err(sdev->dev, "unsupported bus format 0x%x\n", bus_fmt);
return ERR_PTR(-EINVAL);
}
scon = kzalloc(sizeof(*scon), GFP_KERNEL);
if (!scon)
return ERR_PTR(-ENOMEM);
connector = &scon->base;
scon->encoder = encoder;
scon->mode = &sdev->pdata->panel.mode;
info = &connector->display_info;
info->width_mm = sdev->pdata->panel.width_mm;
info->height_mm = sdev->pdata->panel.height_mm;
if (scon->mode->flags & DISPLAY_FLAGS_PIXDATA_POSEDGE)
info->bus_flags |= DRM_BUS_FLAG_PIXDATA_DRIVE_POSEDGE;
if (scon->mode->flags & DISPLAY_FLAGS_DE_LOW)
info->bus_flags |= DRM_BUS_FLAG_DE_LOW;
ret = drm_display_info_set_bus_formats(info, &bus_fmt, 1);
if (ret < 0) {
kfree(scon);
return ERR_PTR(ret);
}
ret = drm_connector_init(&sdev->ddev, connector, &connector_funcs,
DRM_MODE_CONNECTOR_DPI);
if (ret < 0) {
kfree(scon);
return ERR_PTR(ret);
}
drm_connector_helper_add(connector, &connector_helper_funcs);
return connector;
}
/* -----------------------------------------------------------------------------
* Connector
*/
int shmob_drm_connector_create(struct shmob_drm_device *sdev,
struct drm_encoder *encoder)
{
struct drm_connector *connector = &sdev->connector.connector;
struct drm_connector *connector;
int ret;
sdev->connector.encoder = encoder;
connector->display_info.width_mm = sdev->pdata->panel.width_mm;
connector->display_info.height_mm = sdev->pdata->panel.height_mm;
ret = drm_connector_init(sdev->ddev, connector, &connector_funcs,
DRM_MODE_CONNECTOR_LVDS);
if (ret < 0)
return ret;
drm_connector_helper_add(connector, &connector_helper_funcs);
ret = shmob_drm_backlight_init(&sdev->connector);
if (ret < 0)
goto err_cleanup;
if (sdev->pdata)
connector = shmob_drm_connector_init(sdev, encoder);
else
connector = drm_bridge_connector_init(&sdev->ddev, encoder);
if (IS_ERR(connector)) {
dev_err(sdev->dev, "failed to created connector: %pe\n",
connector);
return PTR_ERR(connector);
}
ret = drm_connector_attach_encoder(connector, encoder);
if (ret < 0)
goto err_backlight;
goto error;
drm_helper_connector_dpms(connector, DRM_MODE_DPMS_OFF);
drm_object_property_set_value(&connector->base,
sdev->ddev->mode_config.dpms_property, DRM_MODE_DPMS_OFF);
connector->dpms = DRM_MODE_DPMS_OFF;
sdev->connector = connector;
return 0;
err_backlight:
shmob_drm_backlight_exit(&sdev->connector);
err_cleanup:
error:
drm_connector_cleanup(connector);
return ret;
}

View File

@ -14,39 +14,30 @@
#include <drm/drm_connector.h>
#include <drm/drm_encoder.h>
struct backlight_device;
#include <linux/wait.h>
#include <video/videomode.h>
struct drm_pending_vblank_event;
struct shmob_drm_device;
struct shmob_drm_format_info;
struct shmob_drm_crtc {
struct drm_crtc crtc;
struct drm_crtc base;
struct drm_pending_vblank_event *event;
int dpms;
const struct shmob_drm_format_info *format;
unsigned long dma[2];
unsigned int line_size;
bool started;
};
struct shmob_drm_encoder {
struct drm_encoder encoder;
int dpms;
wait_queue_head_t flip_wait;
};
/* Legacy connector */
struct shmob_drm_connector {
struct drm_connector connector;
struct drm_connector base;
struct drm_encoder *encoder;
struct backlight_device *backlight;
const struct videomode *mode;
};
int shmob_drm_crtc_create(struct shmob_drm_device *sdev);
void shmob_drm_crtc_finish_page_flip(struct shmob_drm_crtc *scrtc);
void shmob_drm_crtc_suspend(struct shmob_drm_crtc *scrtc);
void shmob_drm_crtc_resume(struct shmob_drm_crtc *scrtc);
int shmob_drm_encoder_create(struct shmob_drm_device *sdev);
int shmob_drm_connector_create(struct shmob_drm_device *sdev,

View File

@ -11,13 +11,17 @@
#include <linux/io.h>
#include <linux/mm.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/pm.h>
#include <linux/pm_runtime.h>
#include <linux/slab.h>
#include <drm/drm_atomic_helper.h>
#include <drm/drm_drv.h>
#include <drm/drm_fbdev_generic.h>
#include <drm/drm_gem_dma_helper.h>
#include <drm/drm_modeset_helper.h>
#include <drm/drm_module.h>
#include <drm/drm_probe_helper.h>
#include <drm/drm_vblank.h>
@ -31,57 +35,23 @@
* Hardware initialization
*/
static int shmob_drm_init_interface(struct shmob_drm_device *sdev)
{
static const u32 ldmt1r[] = {
[SHMOB_DRM_IFACE_RGB8] = LDMT1R_MIFTYP_RGB8,
[SHMOB_DRM_IFACE_RGB9] = LDMT1R_MIFTYP_RGB9,
[SHMOB_DRM_IFACE_RGB12A] = LDMT1R_MIFTYP_RGB12A,
[SHMOB_DRM_IFACE_RGB12B] = LDMT1R_MIFTYP_RGB12B,
[SHMOB_DRM_IFACE_RGB16] = LDMT1R_MIFTYP_RGB16,
[SHMOB_DRM_IFACE_RGB18] = LDMT1R_MIFTYP_RGB18,
[SHMOB_DRM_IFACE_RGB24] = LDMT1R_MIFTYP_RGB24,
[SHMOB_DRM_IFACE_YUV422] = LDMT1R_MIFTYP_YCBCR,
[SHMOB_DRM_IFACE_SYS8A] = LDMT1R_IFM | LDMT1R_MIFTYP_SYS8A,
[SHMOB_DRM_IFACE_SYS8B] = LDMT1R_IFM | LDMT1R_MIFTYP_SYS8B,
[SHMOB_DRM_IFACE_SYS8C] = LDMT1R_IFM | LDMT1R_MIFTYP_SYS8C,
[SHMOB_DRM_IFACE_SYS8D] = LDMT1R_IFM | LDMT1R_MIFTYP_SYS8D,
[SHMOB_DRM_IFACE_SYS9] = LDMT1R_IFM | LDMT1R_MIFTYP_SYS9,
[SHMOB_DRM_IFACE_SYS12] = LDMT1R_IFM | LDMT1R_MIFTYP_SYS12,
[SHMOB_DRM_IFACE_SYS16A] = LDMT1R_IFM | LDMT1R_MIFTYP_SYS16A,
[SHMOB_DRM_IFACE_SYS16B] = LDMT1R_IFM | LDMT1R_MIFTYP_SYS16B,
[SHMOB_DRM_IFACE_SYS16C] = LDMT1R_IFM | LDMT1R_MIFTYP_SYS16C,
[SHMOB_DRM_IFACE_SYS18] = LDMT1R_IFM | LDMT1R_MIFTYP_SYS18,
[SHMOB_DRM_IFACE_SYS24] = LDMT1R_IFM | LDMT1R_MIFTYP_SYS24,
};
if (sdev->pdata->iface.interface >= ARRAY_SIZE(ldmt1r)) {
dev_err(sdev->dev, "invalid interface type %u\n",
sdev->pdata->iface.interface);
return -EINVAL;
}
sdev->ldmt1r = ldmt1r[sdev->pdata->iface.interface];
return 0;
}
static int shmob_drm_setup_clocks(struct shmob_drm_device *sdev,
enum shmob_drm_clk_source clksrc)
enum shmob_drm_clk_source clksrc)
{
struct clk *clk;
char *clkname;
switch (clksrc) {
case SHMOB_DRM_CLK_BUS:
clkname = "bus_clk";
clkname = "fck";
sdev->lddckr = LDDCKR_ICKSEL_BUS;
break;
case SHMOB_DRM_CLK_PERIPHERAL:
clkname = "peripheral_clk";
clkname = "media";
sdev->lddckr = LDDCKR_ICKSEL_MIPI;
break;
case SHMOB_DRM_CLK_EXTERNAL:
clkname = NULL;
clkname = "lclk";
sdev->lddckr = LDDCKR_ICKSEL_HDMI;
break;
default:
@ -105,7 +75,7 @@ static int shmob_drm_setup_clocks(struct shmob_drm_device *sdev,
static irqreturn_t shmob_drm_irq(int irq, void *arg)
{
struct drm_device *dev = arg;
struct shmob_drm_device *sdev = dev->dev_private;
struct shmob_drm_device *sdev = to_shmob_device(dev);
unsigned long flags;
u32 status;
@ -119,7 +89,7 @@ static irqreturn_t shmob_drm_irq(int irq, void *arg)
spin_unlock_irqrestore(&sdev->irq_lock, flags);
if (status & LDINTR_VES) {
drm_handle_vblank(dev, 0);
drm_crtc_handle_vblank(&sdev->crtc.base);
shmob_drm_crtc_finish_page_flip(&sdev->crtc);
}
@ -129,7 +99,7 @@ static irqreturn_t shmob_drm_irq(int irq, void *arg)
DEFINE_DRM_GEM_DMA_FOPS(shmob_drm_fops);
static const struct drm_driver shmob_drm_driver = {
.driver_features = DRIVER_GEM | DRIVER_MODESET,
.driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC,
DRM_GEM_DMA_DRIVER_OPS,
.fops = &shmob_drm_fops,
.name = "shmob-drm",
@ -147,26 +117,45 @@ static int shmob_drm_pm_suspend(struct device *dev)
{
struct shmob_drm_device *sdev = dev_get_drvdata(dev);
drm_kms_helper_poll_disable(sdev->ddev);
shmob_drm_crtc_suspend(&sdev->crtc);
return 0;
return drm_mode_config_helper_suspend(&sdev->ddev);
}
static int shmob_drm_pm_resume(struct device *dev)
{
struct shmob_drm_device *sdev = dev_get_drvdata(dev);
drm_modeset_lock_all(sdev->ddev);
shmob_drm_crtc_resume(&sdev->crtc);
drm_modeset_unlock_all(sdev->ddev);
return drm_mode_config_helper_resume(&sdev->ddev);
}
static int shmob_drm_pm_runtime_suspend(struct device *dev)
{
struct shmob_drm_device *sdev = dev_get_drvdata(dev);
if (sdev->clock)
clk_disable_unprepare(sdev->clock);
drm_kms_helper_poll_enable(sdev->ddev);
return 0;
}
static DEFINE_SIMPLE_DEV_PM_OPS(shmob_drm_pm_ops,
shmob_drm_pm_suspend, shmob_drm_pm_resume);
static int shmob_drm_pm_runtime_resume(struct device *dev)
{
struct shmob_drm_device *sdev = dev_get_drvdata(dev);
int ret;
if (sdev->clock) {
ret = clk_prepare_enable(sdev->clock);
if (ret < 0)
return ret;
}
return 0;
}
static const struct dev_pm_ops shmob_drm_pm_ops = {
SYSTEM_SLEEP_PM_OPS(shmob_drm_pm_suspend, shmob_drm_pm_resume)
RUNTIME_PM_OPS(shmob_drm_pm_runtime_suspend,
shmob_drm_pm_runtime_resume, NULL)
};
/* -----------------------------------------------------------------------------
* Platform driver
@ -175,37 +164,45 @@ static DEFINE_SIMPLE_DEV_PM_OPS(shmob_drm_pm_ops,
static void shmob_drm_remove(struct platform_device *pdev)
{
struct shmob_drm_device *sdev = platform_get_drvdata(pdev);
struct drm_device *ddev = sdev->ddev;
struct drm_device *ddev = &sdev->ddev;
drm_dev_unregister(ddev);
drm_atomic_helper_shutdown(ddev);
drm_kms_helper_poll_fini(ddev);
free_irq(sdev->irq, ddev);
drm_dev_put(ddev);
}
static int shmob_drm_probe(struct platform_device *pdev)
{
struct shmob_drm_platform_data *pdata = pdev->dev.platform_data;
const struct shmob_drm_config *config;
struct shmob_drm_device *sdev;
struct drm_device *ddev;
unsigned int i;
int ret;
if (pdata == NULL) {
config = of_device_get_match_data(&pdev->dev);
if (!config && !pdata) {
dev_err(&pdev->dev, "no platform data\n");
return -EINVAL;
}
/*
* Allocate and initialize the driver private data, I/O resources and
* clocks.
* Allocate and initialize the DRM device, driver private data, I/O
* resources and clocks.
*/
sdev = devm_kzalloc(&pdev->dev, sizeof(*sdev), GFP_KERNEL);
if (sdev == NULL)
return -ENOMEM;
sdev = devm_drm_dev_alloc(&pdev->dev, &shmob_drm_driver,
struct shmob_drm_device, ddev);
if (IS_ERR(sdev))
return PTR_ERR(sdev);
ddev = &sdev->ddev;
sdev->dev = &pdev->dev;
sdev->pdata = pdata;
if (config) {
sdev->config = *config;
} else {
sdev->pdata = pdata;
sdev->config.clk_source = pdata->clk_source;
sdev->config.clk_div = pdata->iface.clk_div;
}
spin_lock_init(&sdev->irq_lock);
platform_set_drvdata(pdev, sdev);
@ -214,49 +211,32 @@ static int shmob_drm_probe(struct platform_device *pdev)
if (IS_ERR(sdev->mmio))
return PTR_ERR(sdev->mmio);
ret = shmob_drm_setup_clocks(sdev, pdata->clk_source);
ret = shmob_drm_setup_clocks(sdev, sdev->config.clk_source);
if (ret < 0)
return ret;
ret = shmob_drm_init_interface(sdev);
if (ret < 0)
ret = devm_pm_runtime_enable(&pdev->dev);
if (ret)
return ret;
/* Allocate and initialize the DRM device. */
ddev = drm_dev_alloc(&shmob_drm_driver, &pdev->dev);
if (IS_ERR(ddev))
return PTR_ERR(ddev);
sdev->ddev = ddev;
ddev->dev_private = sdev;
ret = shmob_drm_modeset_init(sdev);
if (ret < 0) {
dev_err(&pdev->dev, "failed to initialize mode setting\n");
goto err_free_drm_dev;
}
for (i = 0; i < 4; ++i) {
ret = shmob_drm_plane_create(sdev, i);
if (ret < 0) {
dev_err(&pdev->dev, "failed to create plane %u\n", i);
goto err_modeset_cleanup;
}
}
ret = drm_vblank_init(ddev, 1);
if (ret < 0) {
dev_err(&pdev->dev, "failed to initialize vblank\n");
goto err_modeset_cleanup;
return ret;
}
ret = shmob_drm_modeset_init(sdev);
if (ret < 0)
return dev_err_probe(&pdev->dev, ret,
"failed to initialize mode setting\n");
ret = platform_get_irq(pdev, 0);
if (ret < 0)
goto err_modeset_cleanup;
sdev->irq = ret;
ret = request_irq(sdev->irq, shmob_drm_irq, 0, ddev->driver->name,
ddev);
ret = devm_request_irq(&pdev->dev, sdev->irq, shmob_drm_irq, 0,
ddev->driver->name, ddev);
if (ret < 0) {
dev_err(&pdev->dev, "failed to install IRQ handler\n");
goto err_modeset_cleanup;
@ -268,28 +248,35 @@ static int shmob_drm_probe(struct platform_device *pdev)
*/
ret = drm_dev_register(ddev, 0);
if (ret < 0)
goto err_irq_uninstall;
goto err_modeset_cleanup;
drm_fbdev_generic_setup(ddev, 16);
return 0;
err_irq_uninstall:
free_irq(sdev->irq, ddev);
err_modeset_cleanup:
drm_kms_helper_poll_fini(ddev);
err_free_drm_dev:
drm_dev_put(ddev);
return ret;
}
static const struct shmob_drm_config shmob_arm_config = {
.clk_source = SHMOB_DRM_CLK_BUS,
.clk_div = 5,
};
static const struct of_device_id shmob_drm_of_table[] __maybe_unused = {
{ .compatible = "renesas,r8a7740-lcdc", .data = &shmob_arm_config, },
{ .compatible = "renesas,sh73a0-lcdc", .data = &shmob_arm_config, },
{ /* sentinel */ }
};
static struct platform_driver shmob_drm_platform_driver = {
.probe = shmob_drm_probe,
.remove_new = shmob_drm_remove,
.driver = {
.name = "shmob-drm",
.pm = pm_sleep_ptr(&shmob_drm_pm_ops),
.of_match_table = of_match_ptr(shmob_drm_of_table),
.pm = &shmob_drm_pm_ops,
},
};

View File

@ -20,23 +20,33 @@ struct clk;
struct device;
struct drm_device;
struct shmob_drm_config {
enum shmob_drm_clk_source clk_source;
unsigned int clk_div;
};
struct shmob_drm_device {
struct device *dev;
const struct shmob_drm_platform_data *pdata;
struct shmob_drm_config config;
void __iomem *mmio;
struct clk *clock;
u32 lddckr;
u32 ldmt1r;
unsigned int irq;
spinlock_t irq_lock; /* Protects hardware LDINTR register */
struct drm_device *ddev;
struct drm_device ddev;
struct shmob_drm_crtc crtc;
struct shmob_drm_encoder encoder;
struct shmob_drm_connector connector;
struct drm_encoder encoder;
struct drm_connector *connector;
};
static inline struct shmob_drm_device *to_shmob_device(struct drm_device *dev)
{
return container_of(dev, struct shmob_drm_device, ddev);
}
#endif /* __SHMOB_DRM_DRV_H__ */

View File

@ -7,6 +7,7 @@
* Laurent Pinchart (laurent.pinchart@ideasonboard.com)
*/
#include <drm/drm_atomic_helper.h>
#include <drm/drm_crtc.h>
#include <drm/drm_crtc_helper.h>
#include <drm/drm_fourcc.h>
@ -17,6 +18,7 @@
#include "shmob_drm_crtc.h"
#include "shmob_drm_drv.h"
#include "shmob_drm_kms.h"
#include "shmob_drm_plane.h"
#include "shmob_drm_regs.h"
/* -----------------------------------------------------------------------------
@ -27,53 +29,73 @@ static const struct shmob_drm_format_info shmob_drm_format_infos[] = {
{
.fourcc = DRM_FORMAT_RGB565,
.bpp = 16,
.yuv = false,
.lddfr = LDDFR_PKF_RGB16,
.ldddsr = LDDDSR_LS | LDDDSR_WS,
.ldbbsifr = LDBBSIFR_AL_1 | LDBBSIFR_SWPL | LDBBSIFR_SWPW |
LDBBSIFR_RY | LDBBSIFR_RPKF_RGB16,
}, {
.fourcc = DRM_FORMAT_RGB888,
.bpp = 24,
.yuv = false,
.lddfr = LDDFR_PKF_RGB24,
.ldddsr = LDDDSR_LS | LDDDSR_WS | LDDDSR_BS,
.ldbbsifr = LDBBSIFR_AL_1 | LDBBSIFR_SWPL | LDBBSIFR_SWPW |
LDBBSIFR_SWPB | LDBBSIFR_RY | LDBBSIFR_RPKF_RGB24,
}, {
.fourcc = DRM_FORMAT_ARGB8888,
.bpp = 32,
.yuv = false,
.lddfr = LDDFR_PKF_ARGB32,
.ldddsr = LDDDSR_LS,
.ldbbsifr = LDBBSIFR_AL_PK | LDBBSIFR_SWPL | LDBBSIFR_RY |
LDBBSIFR_RPKF_ARGB32,
}, {
.fourcc = DRM_FORMAT_XRGB8888,
.bpp = 32,
.yuv = false,
.lddfr = LDDFR_PKF_ARGB32,
.ldddsr = LDDDSR_LS,
.ldbbsifr = LDBBSIFR_AL_1 | LDBBSIFR_SWPL | LDBBSIFR_RY |
LDBBSIFR_RPKF_ARGB32,
}, {
.fourcc = DRM_FORMAT_NV12,
.bpp = 12,
.yuv = true,
.lddfr = LDDFR_CC | LDDFR_YF_420,
.ldddsr = LDDDSR_LS | LDDDSR_WS | LDDDSR_BS,
.ldbbsifr = LDBBSIFR_AL_1 | LDBBSIFR_SWPL | LDBBSIFR_SWPW |
LDBBSIFR_SWPB | LDBBSIFR_CHRR_420,
}, {
.fourcc = DRM_FORMAT_NV21,
.bpp = 12,
.yuv = true,
.lddfr = LDDFR_CC | LDDFR_YF_420,
.ldddsr = LDDDSR_LS | LDDDSR_WS,
.ldbbsifr = LDBBSIFR_AL_1 | LDBBSIFR_SWPL | LDBBSIFR_SWPW |
LDBBSIFR_CHRR_420,
}, {
.fourcc = DRM_FORMAT_NV16,
.bpp = 16,
.yuv = true,
.lddfr = LDDFR_CC | LDDFR_YF_422,
.ldddsr = LDDDSR_LS | LDDDSR_WS | LDDDSR_BS,
.ldbbsifr = LDBBSIFR_AL_1 | LDBBSIFR_SWPL | LDBBSIFR_SWPW |
LDBBSIFR_SWPB | LDBBSIFR_CHRR_422,
}, {
.fourcc = DRM_FORMAT_NV61,
.bpp = 16,
.yuv = true,
.lddfr = LDDFR_CC | LDDFR_YF_422,
.ldddsr = LDDDSR_LS | LDDDSR_WS,
.ldbbsifr = LDBBSIFR_AL_1 | LDBBSIFR_SWPL | LDBBSIFR_SWPW |
LDBBSIFR_CHRR_422,
}, {
.fourcc = DRM_FORMAT_NV24,
.bpp = 24,
.yuv = true,
.lddfr = LDDFR_CC | LDDFR_YF_444,
.ldddsr = LDDDSR_LS | LDDDSR_WS | LDDDSR_BS,
.ldbbsifr = LDBBSIFR_AL_1 | LDBBSIFR_SWPL | LDBBSIFR_SWPW |
LDBBSIFR_SWPB | LDBBSIFR_CHRR_444,
}, {
.fourcc = DRM_FORMAT_NV42,
.bpp = 24,
.yuv = true,
.lddfr = LDDFR_CC | LDDFR_YF_444,
.ldddsr = LDDDSR_LS | LDDDSR_WS,
.ldbbsifr = LDBBSIFR_AL_1 | LDBBSIFR_SWPL | LDBBSIFR_SWPW |
LDBBSIFR_CHRR_444,
},
};
@ -112,7 +134,7 @@ shmob_drm_fb_create(struct drm_device *dev, struct drm_file *file_priv,
return ERR_PTR(-EINVAL);
}
if (format->yuv) {
if (shmob_drm_format_is_yuv(format)) {
unsigned int chroma_cpp = format->bpp == 24 ? 2 : 1;
if (mode_cmd->pitches[1] != mode_cmd->pitches[0] * chroma_cpp) {
@ -127,29 +149,40 @@ shmob_drm_fb_create(struct drm_device *dev, struct drm_file *file_priv,
static const struct drm_mode_config_funcs shmob_drm_mode_config_funcs = {
.fb_create = shmob_drm_fb_create,
.atomic_check = drm_atomic_helper_check,
.atomic_commit = drm_atomic_helper_commit,
};
int shmob_drm_modeset_init(struct shmob_drm_device *sdev)
{
struct drm_device *dev = &sdev->ddev;
int ret;
ret = drmm_mode_config_init(sdev->ddev);
ret = drmm_mode_config_init(dev);
if (ret)
return ret;
shmob_drm_crtc_create(sdev);
shmob_drm_encoder_create(sdev);
shmob_drm_connector_create(sdev, &sdev->encoder.encoder);
ret = shmob_drm_crtc_create(sdev);
if (ret < 0)
return ret;
drm_kms_helper_poll_init(sdev->ddev);
ret = shmob_drm_encoder_create(sdev);
if (ret < 0)
return ret;
sdev->ddev->mode_config.min_width = 0;
sdev->ddev->mode_config.min_height = 0;
sdev->ddev->mode_config.max_width = 4095;
sdev->ddev->mode_config.max_height = 4095;
sdev->ddev->mode_config.funcs = &shmob_drm_mode_config_funcs;
ret = shmob_drm_connector_create(sdev, &sdev->encoder);
if (ret < 0)
return ret;
drm_helper_disable_unused_functions(sdev->ddev);
drm_mode_config_reset(dev);
drm_kms_helper_poll_init(dev);
sdev->ddev.mode_config.min_width = 0;
sdev->ddev.mode_config.min_height = 0;
sdev->ddev.mode_config.max_width = 4095;
sdev->ddev.mode_config.max_height = 4095;
sdev->ddev.mode_config.funcs = &shmob_drm_mode_config_funcs;
return 0;
}

View File

@ -17,11 +17,14 @@ struct shmob_drm_device;
struct shmob_drm_format_info {
u32 fourcc;
unsigned int bpp;
bool yuv;
u32 lddfr;
u32 lddfr; /* LCD Data Format Register */
u16 ldbbsifr; /* CHn Source Image Format Register low bits */
u8 ldddsr; /* LCDC Input Image Data Swap Register low bits */
u8 bpp;
};
#define shmob_drm_format_is_yuv(format) ((format)->lddfr & LDDFR_CC)
const struct shmob_drm_format_info *shmob_drm_format_info(u32 fourcc);
int shmob_drm_modeset_init(struct shmob_drm_device *sdev);

View File

@ -7,11 +7,14 @@
* Laurent Pinchart (laurent.pinchart@ideasonboard.com)
*/
#include <drm/drm_atomic.h>
#include <drm/drm_atomic_helper.h>
#include <drm/drm_crtc.h>
#include <drm/drm_fb_dma_helper.h>
#include <drm/drm_fourcc.h>
#include <drm/drm_framebuffer.h>
#include <drm/drm_gem_dma_helper.h>
#include <drm/drm_plane_helper.h>
#include "shmob_drm_drv.h"
#include "shmob_drm_kms.h"
@ -19,102 +22,84 @@
#include "shmob_drm_regs.h"
struct shmob_drm_plane {
struct drm_plane plane;
struct drm_plane base;
unsigned int index;
unsigned int alpha;
const struct shmob_drm_format_info *format;
unsigned long dma[2];
unsigned int src_x;
unsigned int src_y;
unsigned int crtc_x;
unsigned int crtc_y;
unsigned int crtc_w;
unsigned int crtc_h;
};
#define to_shmob_plane(p) container_of(p, struct shmob_drm_plane, plane)
struct shmob_drm_plane_state {
struct drm_plane_state base;
static void shmob_drm_plane_compute_base(struct shmob_drm_plane *splane,
struct drm_framebuffer *fb,
int x, int y)
const struct shmob_drm_format_info *format;
u32 dma[2];
};
static inline struct shmob_drm_plane *to_shmob_plane(struct drm_plane *plane)
{
return container_of(plane, struct shmob_drm_plane, base);
}
static inline struct shmob_drm_plane_state *to_shmob_plane_state(struct drm_plane_state *state)
{
return container_of(state, struct shmob_drm_plane_state, base);
}
static void shmob_drm_plane_compute_base(struct shmob_drm_plane_state *sstate)
{
struct drm_framebuffer *fb = sstate->base.fb;
unsigned int x = sstate->base.src_x >> 16;
unsigned int y = sstate->base.src_y >> 16;
struct drm_gem_dma_object *gem;
unsigned int bpp;
bpp = splane->format->yuv ? 8 : splane->format->bpp;
bpp = shmob_drm_format_is_yuv(sstate->format) ? 8 : sstate->format->bpp;
gem = drm_fb_dma_get_gem_obj(fb, 0);
splane->dma[0] = gem->dma_addr + fb->offsets[0]
sstate->dma[0] = gem->dma_addr + fb->offsets[0]
+ y * fb->pitches[0] + x * bpp / 8;
if (splane->format->yuv) {
bpp = splane->format->bpp - 8;
if (shmob_drm_format_is_yuv(sstate->format)) {
bpp = sstate->format->bpp - 8;
gem = drm_fb_dma_get_gem_obj(fb, 1);
splane->dma[1] = gem->dma_addr + fb->offsets[1]
sstate->dma[1] = gem->dma_addr + fb->offsets[1]
+ y / (bpp == 4 ? 2 : 1) * fb->pitches[1]
+ x * (bpp == 16 ? 2 : 1);
}
}
static void __shmob_drm_plane_setup(struct shmob_drm_plane *splane,
struct drm_framebuffer *fb)
static void shmob_drm_primary_plane_setup(struct shmob_drm_plane *splane,
struct drm_plane_state *state)
{
struct shmob_drm_device *sdev = splane->plane.dev->dev_private;
struct shmob_drm_plane_state *sstate = to_shmob_plane_state(state);
struct shmob_drm_device *sdev = to_shmob_device(splane->base.dev);
struct drm_framebuffer *fb = state->fb;
/* TODO: Handle YUV colorspaces. Hardcode REC709 for now. */
lcdc_write(sdev, LDDFR, sstate->format->lddfr | LDDFR_CF1);
lcdc_write(sdev, LDMLSR, fb->pitches[0]);
/* Word and long word swap. */
lcdc_write(sdev, LDDDSR, sstate->format->ldddsr);
lcdc_write_mirror(sdev, LDSA1R, sstate->dma[0]);
if (shmob_drm_format_is_yuv(sstate->format))
lcdc_write_mirror(sdev, LDSA2R, sstate->dma[1]);
lcdc_write(sdev, LDRCNTR, lcdc_read(sdev, LDRCNTR) ^ LDRCNTR_MRS);
}
static void shmob_drm_overlay_plane_setup(struct shmob_drm_plane *splane,
struct drm_plane_state *state)
{
struct shmob_drm_plane_state *sstate = to_shmob_plane_state(state);
struct shmob_drm_device *sdev = to_shmob_device(splane->base.dev);
struct drm_framebuffer *fb = state->fb;
u32 format;
/* TODO: Support ROP3 mode */
format = LDBBSIFR_EN | (splane->alpha << LDBBSIFR_LAY_SHIFT);
switch (splane->format->fourcc) {
case DRM_FORMAT_RGB565:
case DRM_FORMAT_NV21:
case DRM_FORMAT_NV61:
case DRM_FORMAT_NV42:
format |= LDBBSIFR_SWPL | LDBBSIFR_SWPW;
break;
case DRM_FORMAT_RGB888:
case DRM_FORMAT_NV12:
case DRM_FORMAT_NV16:
case DRM_FORMAT_NV24:
format |= LDBBSIFR_SWPL | LDBBSIFR_SWPW | LDBBSIFR_SWPB;
break;
case DRM_FORMAT_ARGB8888:
case DRM_FORMAT_XRGB8888:
default:
format |= LDBBSIFR_SWPL;
break;
}
switch (splane->format->fourcc) {
case DRM_FORMAT_RGB565:
format |= LDBBSIFR_AL_1 | LDBBSIFR_RY | LDBBSIFR_RPKF_RGB16;
break;
case DRM_FORMAT_RGB888:
format |= LDBBSIFR_AL_1 | LDBBSIFR_RY | LDBBSIFR_RPKF_RGB24;
break;
case DRM_FORMAT_ARGB8888:
format |= LDBBSIFR_AL_PK | LDBBSIFR_RY | LDDFR_PKF_ARGB32;
break;
case DRM_FORMAT_XRGB8888:
format |= LDBBSIFR_AL_1 | LDBBSIFR_RY | LDDFR_PKF_ARGB32;
break;
case DRM_FORMAT_NV12:
case DRM_FORMAT_NV21:
format |= LDBBSIFR_AL_1 | LDBBSIFR_CHRR_420;
break;
case DRM_FORMAT_NV16:
case DRM_FORMAT_NV61:
format |= LDBBSIFR_AL_1 | LDBBSIFR_CHRR_422;
break;
case DRM_FORMAT_NV24:
case DRM_FORMAT_NV42:
format |= LDBBSIFR_AL_1 | LDBBSIFR_CHRR_444;
break;
}
format = LDBBSIFR_EN | ((state->alpha >> 8) << LDBBSIFR_LAY_SHIFT) |
sstate->format->ldbbsifr;
#define plane_reg_dump(sdev, splane, reg) \
dev_dbg(sdev->ddev->dev, "%s(%u): %s 0x%08x 0x%08x\n", __func__, \
dev_dbg(sdev->ddev.dev, "%s(%u): %s 0x%08x 0x%08x\n", __func__, \
splane->index, #reg, \
lcdc_read(sdev, reg(splane->index)), \
lcdc_read(sdev, reg(splane->index) + LCDC_SIDE_B_OFFSET))
@ -127,29 +112,27 @@ static void __shmob_drm_plane_setup(struct shmob_drm_plane *splane,
plane_reg_dump(sdev, splane, LDBnBSACR);
lcdc_write(sdev, LDBCR, LDBCR_UPC(splane->index));
dev_dbg(sdev->ddev->dev, "%s(%u): %s 0x%08x\n", __func__, splane->index,
dev_dbg(sdev->ddev.dev, "%s(%u): %s 0x%08x\n", __func__, splane->index,
"LDBCR", lcdc_read(sdev, LDBCR));
lcdc_write(sdev, LDBnBSIFR(splane->index), format);
lcdc_write(sdev, LDBnBSSZR(splane->index),
(splane->crtc_h << LDBBSSZR_BVSS_SHIFT) |
(splane->crtc_w << LDBBSSZR_BHSS_SHIFT));
(state->crtc_h << LDBBSSZR_BVSS_SHIFT) |
(state->crtc_w << LDBBSSZR_BHSS_SHIFT));
lcdc_write(sdev, LDBnBLOCR(splane->index),
(splane->crtc_y << LDBBLOCR_CVLC_SHIFT) |
(splane->crtc_x << LDBBLOCR_CHLC_SHIFT));
(state->crtc_y << LDBBLOCR_CVLC_SHIFT) |
(state->crtc_x << LDBBLOCR_CHLC_SHIFT));
lcdc_write(sdev, LDBnBSMWR(splane->index),
fb->pitches[0] << LDBBSMWR_BSMW_SHIFT);
shmob_drm_plane_compute_base(splane, fb, splane->src_x, splane->src_y);
lcdc_write(sdev, LDBnBSAYR(splane->index), splane->dma[0]);
if (splane->format->yuv)
lcdc_write(sdev, LDBnBSACR(splane->index), splane->dma[1]);
lcdc_write(sdev, LDBnBSAYR(splane->index), sstate->dma[0]);
if (shmob_drm_format_is_yuv(sstate->format))
lcdc_write(sdev, LDBnBSACR(splane->index), sstate->dma[1]);
lcdc_write(sdev, LDBCR,
LDBCR_UPF(splane->index) | LDBCR_UPD(splane->index));
dev_dbg(sdev->ddev->dev, "%s(%u): %s 0x%08x\n", __func__, splane->index,
dev_dbg(sdev->ddev.dev, "%s(%u): %s 0x%08x\n", __func__, splane->index,
"LDBCR", lcdc_read(sdev, LDBCR));
plane_reg_dump(sdev, splane, LDBnBSIFR);
@ -160,75 +143,143 @@ static void __shmob_drm_plane_setup(struct shmob_drm_plane *splane,
plane_reg_dump(sdev, splane, LDBnBSACR);
}
void shmob_drm_plane_setup(struct drm_plane *plane)
static int shmob_drm_plane_atomic_check(struct drm_plane *plane,
struct drm_atomic_state *state)
{
struct drm_plane_state *new_plane_state = drm_atomic_get_new_plane_state(state, plane);
struct shmob_drm_plane_state *sstate = to_shmob_plane_state(new_plane_state);
struct drm_crtc_state *crtc_state;
bool is_primary = plane->type == DRM_PLANE_TYPE_PRIMARY;
int ret;
if (!new_plane_state->crtc) {
/*
* The visible field is not reset by the DRM core but only
* updated by drm_atomic_helper_check_plane_state(), set it
* manually.
*/
new_plane_state->visible = false;
sstate->format = NULL;
return 0;
}
crtc_state = drm_atomic_get_crtc_state(state, new_plane_state->crtc);
if (IS_ERR(crtc_state))
return PTR_ERR(crtc_state);
ret = drm_atomic_helper_check_plane_state(new_plane_state, crtc_state,
DRM_PLANE_NO_SCALING,
DRM_PLANE_NO_SCALING,
!is_primary, true);
if (ret < 0)
return ret;
if (!new_plane_state->visible) {
sstate->format = NULL;
return 0;
}
sstate->format = shmob_drm_format_info(new_plane_state->fb->format->format);
if (!sstate->format) {
dev_dbg(plane->dev->dev,
"plane_atomic_check: unsupported format %p4cc\n",
&new_plane_state->fb->format->format);
return -EINVAL;
}
shmob_drm_plane_compute_base(sstate);
return 0;
}
static void shmob_drm_plane_atomic_update(struct drm_plane *plane,
struct drm_atomic_state *state)
{
struct drm_plane_state *new_plane_state = drm_atomic_get_new_plane_state(state, plane);
struct shmob_drm_plane *splane = to_shmob_plane(plane);
if (plane->fb == NULL)
if (!new_plane_state->visible)
return;
__shmob_drm_plane_setup(splane, plane->fb);
if (plane->type == DRM_PLANE_TYPE_PRIMARY)
shmob_drm_primary_plane_setup(splane, new_plane_state);
else
shmob_drm_overlay_plane_setup(splane, new_plane_state);
}
static int
shmob_drm_plane_update(struct drm_plane *plane, struct drm_crtc *crtc,
struct drm_framebuffer *fb, int crtc_x, int crtc_y,
unsigned int crtc_w, unsigned int crtc_h,
uint32_t src_x, uint32_t src_y,
uint32_t src_w, uint32_t src_h,
struct drm_modeset_acquire_ctx *ctx)
static void shmob_drm_plane_atomic_disable(struct drm_plane *plane,
struct drm_atomic_state *state)
{
struct drm_plane_state *old_state = drm_atomic_get_old_plane_state(state, plane);
struct shmob_drm_device *sdev = to_shmob_device(plane->dev);
struct shmob_drm_plane *splane = to_shmob_plane(plane);
struct shmob_drm_device *sdev = plane->dev->dev_private;
const struct shmob_drm_format_info *format;
format = shmob_drm_format_info(fb->format->format);
if (format == NULL) {
dev_dbg(sdev->dev, "update_plane: unsupported format %08x\n",
fb->format->format);
return -EINVAL;
}
if (!old_state->crtc)
return;
if (src_w >> 16 != crtc_w || src_h >> 16 != crtc_h) {
dev_dbg(sdev->dev, "%s: scaling not supported\n", __func__);
return -EINVAL;
}
splane->format = format;
splane->src_x = src_x >> 16;
splane->src_y = src_y >> 16;
splane->crtc_x = crtc_x;
splane->crtc_y = crtc_y;
splane->crtc_w = crtc_w;
splane->crtc_h = crtc_h;
__shmob_drm_plane_setup(splane, fb);
return 0;
}
static int shmob_drm_plane_disable(struct drm_plane *plane,
struct drm_modeset_acquire_ctx *ctx)
{
struct shmob_drm_plane *splane = to_shmob_plane(plane);
struct shmob_drm_device *sdev = plane->dev->dev_private;
splane->format = NULL;
if (plane->type != DRM_PLANE_TYPE_OVERLAY)
return;
lcdc_write(sdev, LDBCR, LDBCR_UPC(splane->index));
lcdc_write(sdev, LDBnBSIFR(splane->index), 0);
return 0;
lcdc_write(sdev, LDBCR,
LDBCR_UPF(splane->index) | LDBCR_UPD(splane->index));
}
static void shmob_drm_plane_destroy(struct drm_plane *plane)
static struct drm_plane_state *
shmob_drm_plane_atomic_duplicate_state(struct drm_plane *plane)
{
drm_plane_force_disable(plane);
drm_plane_cleanup(plane);
struct shmob_drm_plane_state *state;
struct shmob_drm_plane_state *copy;
if (WARN_ON(!plane->state))
return NULL;
state = to_shmob_plane_state(plane->state);
copy = kmemdup(state, sizeof(*state), GFP_KERNEL);
if (copy == NULL)
return NULL;
__drm_atomic_helper_plane_duplicate_state(plane, &copy->base);
return &copy->base;
}
static void shmob_drm_plane_atomic_destroy_state(struct drm_plane *plane,
struct drm_plane_state *state)
{
__drm_atomic_helper_plane_destroy_state(state);
kfree(to_shmob_plane_state(state));
}
static void shmob_drm_plane_reset(struct drm_plane *plane)
{
struct shmob_drm_plane_state *state;
if (plane->state) {
shmob_drm_plane_atomic_destroy_state(plane, plane->state);
plane->state = NULL;
}
state = kzalloc(sizeof(*state), GFP_KERNEL);
if (state == NULL)
return;
__drm_atomic_helper_plane_reset(plane, &state->base);
}
static const struct drm_plane_helper_funcs shmob_drm_plane_helper_funcs = {
.atomic_check = shmob_drm_plane_atomic_check,
.atomic_update = shmob_drm_plane_atomic_update,
.atomic_disable = shmob_drm_plane_atomic_disable,
};
static const struct drm_plane_funcs shmob_drm_plane_funcs = {
.update_plane = shmob_drm_plane_update,
.disable_plane = shmob_drm_plane_disable,
.destroy = shmob_drm_plane_destroy,
.update_plane = drm_atomic_helper_update_plane,
.disable_plane = drm_atomic_helper_disable_plane,
.reset = shmob_drm_plane_reset,
.atomic_duplicate_state = shmob_drm_plane_atomic_duplicate_state,
.atomic_destroy_state = shmob_drm_plane_atomic_destroy_state,
};
static const uint32_t formats[] = {
@ -244,22 +295,23 @@ static const uint32_t formats[] = {
DRM_FORMAT_NV42,
};
int shmob_drm_plane_create(struct shmob_drm_device *sdev, unsigned int index)
struct drm_plane *shmob_drm_plane_create(struct shmob_drm_device *sdev,
enum drm_plane_type type,
unsigned int index)
{
struct shmob_drm_plane *splane;
int ret;
splane = devm_kzalloc(sdev->dev, sizeof(*splane), GFP_KERNEL);
if (splane == NULL)
return -ENOMEM;
splane = drmm_universal_plane_alloc(&sdev->ddev,
struct shmob_drm_plane, base, 1,
&shmob_drm_plane_funcs, formats,
ARRAY_SIZE(formats), NULL, type,
NULL);
if (IS_ERR(splane))
return ERR_CAST(splane);
splane->index = index;
splane->alpha = 255;
ret = drm_universal_plane_init(sdev->ddev, &splane->plane, 1,
&shmob_drm_plane_funcs,
formats, ARRAY_SIZE(formats), NULL,
DRM_PLANE_TYPE_OVERLAY, NULL);
drm_plane_helper_add(&splane->base, &shmob_drm_plane_helper_funcs);
return ret;
return &splane->base;
}

View File

@ -13,7 +13,8 @@
struct drm_plane;
struct shmob_drm_device;
int shmob_drm_plane_create(struct shmob_drm_device *sdev, unsigned int index);
void shmob_drm_plane_setup(struct drm_plane *plane);
struct drm_plane *shmob_drm_plane_create(struct shmob_drm_device *sdev,
enum drm_plane_type type,
unsigned int index);
#endif /* __SHMOB_DRM_PLANE_H__ */

View File

@ -910,7 +910,7 @@ static int ssd132x_primary_plane_atomic_check(struct drm_plane *plane,
struct drm_plane_state *plane_state = drm_atomic_get_new_plane_state(state, plane);
struct ssd130x_plane_state *ssd130x_state = to_ssd130x_plane_state(plane_state);
struct drm_crtc *crtc = plane_state->crtc;
struct drm_crtc_state *crtc_state;
struct drm_crtc_state *crtc_state = NULL;
const struct drm_format_info *fi;
unsigned int pitch;
int ret;

View File

@ -68,4 +68,9 @@ enum amd_asic_type {
extern const char *amdgpu_asic_name[];
struct amdgpu_asic_type_quirk {
unsigned short device; /* PCI device ID */
u8 revision; /* revision ID */
unsigned short type; /* real ASIC type */
};
#endif /*__AMD_ASIC_TYPE_H__ */

View File

@ -10,7 +10,7 @@
#ifndef __SHMOB_DRM_H__
#define __SHMOB_DRM_H__
#include <drm/drm_mode.h>
#include <video/videomode.h>
enum shmob_drm_clk_source {
SHMOB_DRM_CLK_BUS,
@ -18,72 +18,21 @@ enum shmob_drm_clk_source {
SHMOB_DRM_CLK_EXTERNAL,
};
enum shmob_drm_interface {
SHMOB_DRM_IFACE_RGB8, /* 24bpp, 8:8:8 */
SHMOB_DRM_IFACE_RGB9, /* 18bpp, 9:9 */
SHMOB_DRM_IFACE_RGB12A, /* 24bpp, 12:12 */
SHMOB_DRM_IFACE_RGB12B, /* 12bpp */
SHMOB_DRM_IFACE_RGB16, /* 16bpp */
SHMOB_DRM_IFACE_RGB18, /* 18bpp */
SHMOB_DRM_IFACE_RGB24, /* 24bpp */
SHMOB_DRM_IFACE_YUV422, /* 16bpp */
SHMOB_DRM_IFACE_SYS8A, /* 24bpp, 8:8:8 */
SHMOB_DRM_IFACE_SYS8B, /* 18bpp, 8:8:2 */
SHMOB_DRM_IFACE_SYS8C, /* 18bpp, 2:8:8 */
SHMOB_DRM_IFACE_SYS8D, /* 16bpp, 8:8 */
SHMOB_DRM_IFACE_SYS9, /* 18bpp, 9:9 */
SHMOB_DRM_IFACE_SYS12, /* 24bpp, 12:12 */
SHMOB_DRM_IFACE_SYS16A, /* 16bpp */
SHMOB_DRM_IFACE_SYS16B, /* 18bpp, 16:2 */
SHMOB_DRM_IFACE_SYS16C, /* 18bpp, 2:16 */
SHMOB_DRM_IFACE_SYS18, /* 18bpp */
SHMOB_DRM_IFACE_SYS24, /* 24bpp */
};
struct shmob_drm_backlight_data {
const char *name;
int max_brightness;
int (*get_brightness)(void);
int (*set_brightness)(int brightness);
};
struct shmob_drm_panel_data {
unsigned int width_mm; /* Panel width in mm */
unsigned int height_mm; /* Panel height in mm */
struct drm_mode_modeinfo mode;
struct videomode mode;
};
struct shmob_drm_sys_interface_data {
unsigned int read_latch:6;
unsigned int read_setup:8;
unsigned int read_cycle:8;
unsigned int read_strobe:8;
unsigned int write_setup:8;
unsigned int write_cycle:8;
unsigned int write_strobe:8;
unsigned int cs_setup:3;
unsigned int vsync_active_high:1;
unsigned int vsync_dir_input:1;
};
#define SHMOB_DRM_IFACE_FL_DWPOL (1 << 0) /* Rising edge dot clock data latch */
#define SHMOB_DRM_IFACE_FL_DIPOL (1 << 1) /* Active low display enable */
#define SHMOB_DRM_IFACE_FL_DAPOL (1 << 2) /* Active low display data */
#define SHMOB_DRM_IFACE_FL_HSCNT (1 << 3) /* Disable HSYNC during VBLANK */
#define SHMOB_DRM_IFACE_FL_DWCNT (1 << 4) /* Disable dotclock during blanking */
struct shmob_drm_interface_data {
enum shmob_drm_interface interface;
struct shmob_drm_sys_interface_data sys;
unsigned int bus_fmt; /* MEDIA_BUS_FMT_* */
unsigned int clk_div;
unsigned int flags;
};
struct shmob_drm_platform_data {
enum shmob_drm_clk_source clk_source;
struct shmob_drm_interface_data iface;
struct shmob_drm_panel_data panel;
struct shmob_drm_backlight_data backlight;
};
#endif /* __SHMOB_DRM_H__ */

View File

@ -34,7 +34,7 @@
#define MEDIA_BUS_FMT_FIXED 0x0001
/* RGB - next is 0x1025 */
/* RGB - next is 0x1026 */
#define MEDIA_BUS_FMT_RGB444_1X12 0x1016
#define MEDIA_BUS_FMT_RGB444_2X8_PADHI_BE 0x1001
#define MEDIA_BUS_FMT_RGB444_2X8_PADHI_LE 0x1002
@ -46,6 +46,7 @@
#define MEDIA_BUS_FMT_RGB565_2X8_BE 0x1007
#define MEDIA_BUS_FMT_RGB565_2X8_LE 0x1008
#define MEDIA_BUS_FMT_RGB666_1X18 0x1009
#define MEDIA_BUS_FMT_RGB666_2X9_BE 0x1025
#define MEDIA_BUS_FMT_BGR666_1X18 0x1023
#define MEDIA_BUS_FMT_RBG888_1X24 0x100e
#define MEDIA_BUS_FMT_RGB666_1X24_CPADHI 0x1015

View File

@ -17,7 +17,7 @@ settings of all cores, see cpupower(1) how to choose specific cores.
.SH "DOCUMENTATION"
kernel sources:
Documentation/power/powercap/powercap.txt
Documentation/power/powercap/powercap.rst
.SH "SEE ALSO"