|
@@ -27,6 +27,7 @@
|
|
|
#include <drm/amdgpu_drm.h>
|
|
|
#include "amdgpu.h"
|
|
|
#include "amdgpu_atombios.h"
|
|
|
+#include "amdgpu_atomfirmware.h"
|
|
|
#include "amdgpu_i2c.h"
|
|
|
|
|
|
#include "atom.h"
|
|
@@ -1699,7 +1700,7 @@ void amdgpu_atombios_scratch_regs_lock(struct amdgpu_device *adev, bool lock)
|
|
|
WREG32(adev->bios_scratch_reg_offset + 6, bios_6_scratch);
|
|
|
}
|
|
|
|
|
|
-void amdgpu_atombios_scratch_regs_init(struct amdgpu_device *adev)
|
|
|
+static void amdgpu_atombios_scratch_regs_init(struct amdgpu_device *adev)
|
|
|
{
|
|
|
uint32_t bios_2_scratch, bios_6_scratch;
|
|
|
|
|
@@ -1776,7 +1777,7 @@ void amdgpu_atombios_copy_swap(u8 *dst, u8 *src, u8 num_bytes, bool to_le)
|
|
|
#endif
|
|
|
}
|
|
|
|
|
|
-int amdgpu_atombios_allocate_fb_scratch(struct amdgpu_device *adev)
|
|
|
+static int amdgpu_atombios_allocate_fb_scratch(struct amdgpu_device *adev)
|
|
|
{
|
|
|
struct atom_context *ctx = adev->mode_info.atom_context;
|
|
|
int index = GetIndexIntoMasterTable(DATA, VRAM_UsageByFirmware);
|
|
@@ -1819,3 +1820,234 @@ int amdgpu_atombios_allocate_fb_scratch(struct amdgpu_device *adev)
|
|
|
ctx->scratch_size_bytes = usage_bytes;
|
|
|
return 0;
|
|
|
}
|
|
|
+
|
|
|
+/* ATOM accessor methods */
|
|
|
+/*
|
|
|
+ * ATOM is an interpreted byte code stored in tables in the vbios. The
|
|
|
+ * driver registers callbacks to access registers and the interpreter
|
|
|
+ * in the driver parses the tables and executes then to program specific
|
|
|
+ * actions (set display modes, asic init, etc.). See amdgpu_atombios.c,
|
|
|
+ * atombios.h, and atom.c
|
|
|
+ */
|
|
|
+
|
|
|
+/**
|
|
|
+ * cail_pll_read - read PLL register
|
|
|
+ *
|
|
|
+ * @info: atom card_info pointer
|
|
|
+ * @reg: PLL register offset
|
|
|
+ *
|
|
|
+ * Provides a PLL register accessor for the atom interpreter (r4xx+).
|
|
|
+ * Returns the value of the PLL register.
|
|
|
+ */
|
|
|
+static uint32_t cail_pll_read(struct card_info *info, uint32_t reg)
|
|
|
+{
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * cail_pll_write - write PLL register
|
|
|
+ *
|
|
|
+ * @info: atom card_info pointer
|
|
|
+ * @reg: PLL register offset
|
|
|
+ * @val: value to write to the pll register
|
|
|
+ *
|
|
|
+ * Provides a PLL register accessor for the atom interpreter (r4xx+).
|
|
|
+ */
|
|
|
+static void cail_pll_write(struct card_info *info, uint32_t reg, uint32_t val)
|
|
|
+{
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * cail_mc_read - read MC (Memory Controller) register
|
|
|
+ *
|
|
|
+ * @info: atom card_info pointer
|
|
|
+ * @reg: MC register offset
|
|
|
+ *
|
|
|
+ * Provides an MC register accessor for the atom interpreter (r4xx+).
|
|
|
+ * Returns the value of the MC register.
|
|
|
+ */
|
|
|
+static uint32_t cail_mc_read(struct card_info *info, uint32_t reg)
|
|
|
+{
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * cail_mc_write - write MC (Memory Controller) register
|
|
|
+ *
|
|
|
+ * @info: atom card_info pointer
|
|
|
+ * @reg: MC register offset
|
|
|
+ * @val: value to write to the pll register
|
|
|
+ *
|
|
|
+ * Provides a MC register accessor for the atom interpreter (r4xx+).
|
|
|
+ */
|
|
|
+static void cail_mc_write(struct card_info *info, uint32_t reg, uint32_t val)
|
|
|
+{
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * cail_reg_write - write MMIO register
|
|
|
+ *
|
|
|
+ * @info: atom card_info pointer
|
|
|
+ * @reg: MMIO register offset
|
|
|
+ * @val: value to write to the pll register
|
|
|
+ *
|
|
|
+ * Provides a MMIO register accessor for the atom interpreter (r4xx+).
|
|
|
+ */
|
|
|
+static void cail_reg_write(struct card_info *info, uint32_t reg, uint32_t val)
|
|
|
+{
|
|
|
+ struct amdgpu_device *adev = info->dev->dev_private;
|
|
|
+
|
|
|
+ WREG32(reg, val);
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * cail_reg_read - read MMIO register
|
|
|
+ *
|
|
|
+ * @info: atom card_info pointer
|
|
|
+ * @reg: MMIO register offset
|
|
|
+ *
|
|
|
+ * Provides an MMIO register accessor for the atom interpreter (r4xx+).
|
|
|
+ * Returns the value of the MMIO register.
|
|
|
+ */
|
|
|
+static uint32_t cail_reg_read(struct card_info *info, uint32_t reg)
|
|
|
+{
|
|
|
+ struct amdgpu_device *adev = info->dev->dev_private;
|
|
|
+ uint32_t r;
|
|
|
+
|
|
|
+ r = RREG32(reg);
|
|
|
+ return r;
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * cail_ioreg_write - write IO register
|
|
|
+ *
|
|
|
+ * @info: atom card_info pointer
|
|
|
+ * @reg: IO register offset
|
|
|
+ * @val: value to write to the pll register
|
|
|
+ *
|
|
|
+ * Provides a IO register accessor for the atom interpreter (r4xx+).
|
|
|
+ */
|
|
|
+static void cail_ioreg_write(struct card_info *info, uint32_t reg, uint32_t val)
|
|
|
+{
|
|
|
+ struct amdgpu_device *adev = info->dev->dev_private;
|
|
|
+
|
|
|
+ WREG32_IO(reg, val);
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * cail_ioreg_read - read IO register
|
|
|
+ *
|
|
|
+ * @info: atom card_info pointer
|
|
|
+ * @reg: IO register offset
|
|
|
+ *
|
|
|
+ * Provides an IO register accessor for the atom interpreter (r4xx+).
|
|
|
+ * Returns the value of the IO register.
|
|
|
+ */
|
|
|
+static uint32_t cail_ioreg_read(struct card_info *info, uint32_t reg)
|
|
|
+{
|
|
|
+ struct amdgpu_device *adev = info->dev->dev_private;
|
|
|
+ uint32_t r;
|
|
|
+
|
|
|
+ r = RREG32_IO(reg);
|
|
|
+ return r;
|
|
|
+}
|
|
|
+
|
|
|
+static ssize_t amdgpu_atombios_get_vbios_version(struct device *dev,
|
|
|
+ struct device_attribute *attr,
|
|
|
+ char *buf)
|
|
|
+{
|
|
|
+ struct drm_device *ddev = dev_get_drvdata(dev);
|
|
|
+ struct amdgpu_device *adev = ddev->dev_private;
|
|
|
+ struct atom_context *ctx = adev->mode_info.atom_context;
|
|
|
+
|
|
|
+ return snprintf(buf, PAGE_SIZE, "%s\n", ctx->vbios_version);
|
|
|
+}
|
|
|
+
|
|
|
+static DEVICE_ATTR(vbios_version, 0444, amdgpu_atombios_get_vbios_version,
|
|
|
+ NULL);
|
|
|
+
|
|
|
+/**
|
|
|
+ * amdgpu_atombios_fini - free the driver info and callbacks for atombios
|
|
|
+ *
|
|
|
+ * @adev: amdgpu_device pointer
|
|
|
+ *
|
|
|
+ * Frees the driver info and register access callbacks for the ATOM
|
|
|
+ * interpreter (r4xx+).
|
|
|
+ * Called at driver shutdown.
|
|
|
+ */
|
|
|
+void amdgpu_atombios_fini(struct amdgpu_device *adev)
|
|
|
+{
|
|
|
+ if (adev->mode_info.atom_context) {
|
|
|
+ kfree(adev->mode_info.atom_context->scratch);
|
|
|
+ kfree(adev->mode_info.atom_context->iio);
|
|
|
+ }
|
|
|
+ kfree(adev->mode_info.atom_context);
|
|
|
+ adev->mode_info.atom_context = NULL;
|
|
|
+ kfree(adev->mode_info.atom_card_info);
|
|
|
+ adev->mode_info.atom_card_info = NULL;
|
|
|
+ device_remove_file(adev->dev, &dev_attr_vbios_version);
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * amdgpu_atombios_init - init the driver info and callbacks for atombios
|
|
|
+ *
|
|
|
+ * @adev: amdgpu_device pointer
|
|
|
+ *
|
|
|
+ * Initializes the driver info and register access callbacks for the
|
|
|
+ * ATOM interpreter (r4xx+).
|
|
|
+ * Returns 0 on sucess, -ENOMEM on failure.
|
|
|
+ * Called at driver startup.
|
|
|
+ */
|
|
|
+int amdgpu_atombios_init(struct amdgpu_device *adev)
|
|
|
+{
|
|
|
+ struct card_info *atom_card_info =
|
|
|
+ kzalloc(sizeof(struct card_info), GFP_KERNEL);
|
|
|
+ int ret;
|
|
|
+
|
|
|
+ if (!atom_card_info)
|
|
|
+ return -ENOMEM;
|
|
|
+
|
|
|
+ adev->mode_info.atom_card_info = atom_card_info;
|
|
|
+ atom_card_info->dev = adev->ddev;
|
|
|
+ atom_card_info->reg_read = cail_reg_read;
|
|
|
+ atom_card_info->reg_write = cail_reg_write;
|
|
|
+ /* needed for iio ops */
|
|
|
+ if (adev->rio_mem) {
|
|
|
+ atom_card_info->ioreg_read = cail_ioreg_read;
|
|
|
+ atom_card_info->ioreg_write = cail_ioreg_write;
|
|
|
+ } else {
|
|
|
+ DRM_DEBUG("PCI I/O BAR is not found. Using MMIO to access ATOM BIOS\n");
|
|
|
+ atom_card_info->ioreg_read = cail_reg_read;
|
|
|
+ atom_card_info->ioreg_write = cail_reg_write;
|
|
|
+ }
|
|
|
+ atom_card_info->mc_read = cail_mc_read;
|
|
|
+ atom_card_info->mc_write = cail_mc_write;
|
|
|
+ atom_card_info->pll_read = cail_pll_read;
|
|
|
+ atom_card_info->pll_write = cail_pll_write;
|
|
|
+
|
|
|
+ adev->mode_info.atom_context = amdgpu_atom_parse(atom_card_info, adev->bios);
|
|
|
+ if (!adev->mode_info.atom_context) {
|
|
|
+ amdgpu_atombios_fini(adev);
|
|
|
+ return -ENOMEM;
|
|
|
+ }
|
|
|
+
|
|
|
+ mutex_init(&adev->mode_info.atom_context->mutex);
|
|
|
+ if (adev->is_atom_fw) {
|
|
|
+ amdgpu_atomfirmware_scratch_regs_init(adev);
|
|
|
+ amdgpu_atomfirmware_allocate_fb_scratch(adev);
|
|
|
+ } else {
|
|
|
+ amdgpu_atombios_scratch_regs_init(adev);
|
|
|
+ amdgpu_atombios_allocate_fb_scratch(adev);
|
|
|
+ }
|
|
|
+
|
|
|
+ ret = device_create_file(adev->dev, &dev_attr_vbios_version);
|
|
|
+ if (ret) {
|
|
|
+ DRM_ERROR("Failed to create device file for VBIOS version\n");
|
|
|
+ return ret;
|
|
|
+ }
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|