|
@@ -21,6 +21,118 @@
|
|
|
# include <mach/kgsl.h>
|
|
|
#endif
|
|
|
|
|
|
+#define ANY_ID 0xff
|
|
|
+
|
|
|
+struct msm_gpu *a3xx_gpu_init(struct drm_device *dev);
|
|
|
+
|
|
|
+static const struct adreno_info gpulist[] = {
|
|
|
+ {
|
|
|
+ .rev = ADRENO_REV(3, 0, 5, ANY_ID),
|
|
|
+ .revn = 305,
|
|
|
+ .name = "A305",
|
|
|
+ .pm4fw = "a300_pm4.fw",
|
|
|
+ .pfpfw = "a300_pfp.fw",
|
|
|
+ .gmem = SZ_256K,
|
|
|
+ .init = a3xx_gpu_init,
|
|
|
+ }, {
|
|
|
+ .rev = ADRENO_REV(3, 2, ANY_ID, ANY_ID),
|
|
|
+ .revn = 320,
|
|
|
+ .name = "A320",
|
|
|
+ .pm4fw = "a300_pm4.fw",
|
|
|
+ .pfpfw = "a300_pfp.fw",
|
|
|
+ .gmem = SZ_512K,
|
|
|
+ .init = a3xx_gpu_init,
|
|
|
+ }, {
|
|
|
+ .rev = ADRENO_REV(3, 3, 0, ANY_ID),
|
|
|
+ .revn = 330,
|
|
|
+ .name = "A330",
|
|
|
+ .pm4fw = "a330_pm4.fw",
|
|
|
+ .pfpfw = "a330_pfp.fw",
|
|
|
+ .gmem = SZ_1M,
|
|
|
+ .init = a3xx_gpu_init,
|
|
|
+ },
|
|
|
+};
|
|
|
+
|
|
|
+MODULE_FIRMWARE("a300_pm4.fw");
|
|
|
+MODULE_FIRMWARE("a300_pfp.fw");
|
|
|
+MODULE_FIRMWARE("a330_pm4.fw");
|
|
|
+MODULE_FIRMWARE("a330_pfp.fw");
|
|
|
+
|
|
|
+static inline bool _rev_match(uint8_t entry, uint8_t id)
|
|
|
+{
|
|
|
+ return (entry == ANY_ID) || (entry == id);
|
|
|
+}
|
|
|
+
|
|
|
+const struct adreno_info *adreno_info(struct adreno_rev rev)
|
|
|
+{
|
|
|
+ int i;
|
|
|
+
|
|
|
+ /* identify gpu: */
|
|
|
+ for (i = 0; i < ARRAY_SIZE(gpulist); i++) {
|
|
|
+ const struct adreno_info *info = &gpulist[i];
|
|
|
+ if (_rev_match(info->rev.core, rev.core) &&
|
|
|
+ _rev_match(info->rev.major, rev.major) &&
|
|
|
+ _rev_match(info->rev.minor, rev.minor) &&
|
|
|
+ _rev_match(info->rev.patchid, rev.patchid))
|
|
|
+ return info;
|
|
|
+ }
|
|
|
+
|
|
|
+ return NULL;
|
|
|
+}
|
|
|
+
|
|
|
+struct msm_gpu *adreno_load_gpu(struct drm_device *dev)
|
|
|
+{
|
|
|
+ struct msm_drm_private *priv = dev->dev_private;
|
|
|
+ struct platform_device *pdev = priv->gpu_pdev;
|
|
|
+ struct adreno_platform_config *config;
|
|
|
+ struct adreno_rev rev;
|
|
|
+ const struct adreno_info *info;
|
|
|
+ struct msm_gpu *gpu = NULL;
|
|
|
+
|
|
|
+ if (!pdev) {
|
|
|
+ dev_err(dev->dev, "no adreno device\n");
|
|
|
+ return NULL;
|
|
|
+ }
|
|
|
+
|
|
|
+ config = pdev->dev.platform_data;
|
|
|
+ rev = config->rev;
|
|
|
+ info = adreno_info(config->rev);
|
|
|
+
|
|
|
+ if (!info) {
|
|
|
+ dev_warn(dev->dev, "Unknown GPU revision: %u.%u.%u.%u\n",
|
|
|
+ rev.core, rev.major, rev.minor, rev.patchid);
|
|
|
+ return NULL;
|
|
|
+ }
|
|
|
+
|
|
|
+ DBG("Found GPU: %u.%u.%u.%u", rev.core, rev.major,
|
|
|
+ rev.minor, rev.patchid);
|
|
|
+
|
|
|
+ gpu = info->init(dev);
|
|
|
+ if (IS_ERR(gpu)) {
|
|
|
+ dev_warn(dev->dev, "failed to load adreno gpu\n");
|
|
|
+ gpu = NULL;
|
|
|
+ /* not fatal */
|
|
|
+ }
|
|
|
+
|
|
|
+ if (gpu) {
|
|
|
+ int ret;
|
|
|
+ mutex_lock(&dev->struct_mutex);
|
|
|
+ gpu->funcs->pm_resume(gpu);
|
|
|
+ mutex_unlock(&dev->struct_mutex);
|
|
|
+ ret = gpu->funcs->hw_init(gpu);
|
|
|
+ if (ret) {
|
|
|
+ dev_err(dev->dev, "gpu hw init failed: %d\n", ret);
|
|
|
+ gpu->funcs->destroy(gpu);
|
|
|
+ gpu = NULL;
|
|
|
+ } else {
|
|
|
+ /* give inactive pm a chance to kick in: */
|
|
|
+ msm_gpu_retire(gpu);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return gpu;
|
|
|
+}
|
|
|
+
|
|
|
static void set_gpu_pdev(struct drm_device *dev,
|
|
|
struct platform_device *pdev)
|
|
|
{
|