mirror of
https://github.com/armbian/linux-cix.git
synced 2026-01-06 12:30:45 -08:00
Merge tag 'drm-fixes-2023-01-13' of git://anongit.freedesktop.org/drm/drm
Pull drm fixes from Dave Airlie: "There is a bit of a post-holiday build up here I expect, small fixes across the board, amdgpu and msm being the main leaders, with others having a few. One code removal patch for nouveau: buddy: - benchmark regression fix for top-down buddy allocation panel: - add Lenovo panel orientation quirk ttm: - fix kernel oops regression amdgpu: - fix missing fence references - fix missing pipeline sync fencing - SMU13 fan speed fix - SMU13 fix power cap handling - SMU13 BACO fix - Fix a possible segfault in bo validation error case - Delay removal of firmware framebuffer - Fix error when unloading amdkfd: - SVM fix when clearing vram - GC11 fix for multi-GPU i915: - Reserve enough fence slot for i915_vma_unbind_vsync - Fix potential use after free - Reset engines twice in case of reset failure - Use multi-cast registers for SVG Unit registers msm: - display: - doc warning fixes - dt attribs cleanups - memory leak fix - error handing in hdmi probe fix - dp_aux_isr incorrect signalling fix - shutdown path fix - accel: - a5xx: fix quirks to be a bitmask - a6xx: fix gx halt to avoid 1s hang - kexec shutdown fix - fix potential double free vmwgfx: - drop rcu usage to make code more robust virtio: - fix use-after-free in gem handle code nouveau: - drop unused nouveau_fbcon.c" * tag 'drm-fixes-2023-01-13' of git://anongit.freedesktop.org/drm/drm: (35 commits) drm: Optimize drm buddy top-down allocation method drm/ttm: Fix a regression causing kernel oops'es drm/i915/gt: Cover rest of SVG unit MCR registers drm/nouveau: Remove file nouveau_fbcon.c drm/amdkfd: Fix NULL pointer error for GC 11.0.1 on mGPU drm/amd/pm/smu13: BACO is supported when it's in BACO state drm/amdkfd: Add sync after creating vram bo drm/i915/gt: Reset twice drm/amdgpu: fix pipeline sync v2 drm/vmwgfx: Remove rcu locks from user resources drm/virtio: Fix GEM handle creation UAF drm/amdgpu: Fixed bug on error when unloading amdgpu drm/amd: Delay removal of the firmware framebuffer drm/amdgpu: Fix potential NULL dereference drm/i915: Fix potential context UAFs drm/i915: Reserve enough fence slot for i915_vma_unbind_async drm: Add orientation quirk for Lenovo ideapad D330-10IGL drm/msm/a6xx: Avoid gx gbit halt during rpm suspend drm/msm/adreno: Make adreno quirks not overwrite each other drm/msm: another fix for the headless Adreno GPU ...
This commit is contained in:
@@ -32,7 +32,7 @@ properties:
|
||||
- description: Display byte clock
|
||||
- description: Display byte interface clock
|
||||
- description: Display pixel clock
|
||||
- description: Display escape clock
|
||||
- description: Display core clock
|
||||
- description: Display AHB clock
|
||||
- description: Display AXI clock
|
||||
|
||||
@@ -137,8 +137,6 @@ required:
|
||||
- phys
|
||||
- assigned-clocks
|
||||
- assigned-clock-parents
|
||||
- power-domains
|
||||
- operating-points-v2
|
||||
- ports
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
@@ -69,7 +69,6 @@ required:
|
||||
- compatible
|
||||
- reg
|
||||
- reg-names
|
||||
- vdds-supply
|
||||
|
||||
unevaluatedProperties: false
|
||||
|
||||
|
||||
@@ -39,7 +39,6 @@ required:
|
||||
- compatible
|
||||
- reg
|
||||
- reg-names
|
||||
- vcca-supply
|
||||
|
||||
unevaluatedProperties: false
|
||||
|
||||
|
||||
@@ -34,6 +34,10 @@ properties:
|
||||
vddio-supply:
|
||||
description: Phandle to vdd-io regulator device node.
|
||||
|
||||
qcom,dsi-phy-regulator-ldo-mode:
|
||||
type: boolean
|
||||
description: Indicates if the LDO mode PHY regulator is wanted.
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
|
||||
@@ -72,7 +72,7 @@ examples:
|
||||
#include <dt-bindings/interconnect/qcom,qcm2290.h>
|
||||
#include <dt-bindings/power/qcom-rpmpd.h>
|
||||
|
||||
mdss@5e00000 {
|
||||
display-subsystem@5e00000 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
compatible = "qcom,qcm2290-mdss";
|
||||
|
||||
@@ -62,7 +62,7 @@ examples:
|
||||
#include <dt-bindings/interrupt-controller/arm-gic.h>
|
||||
#include <dt-bindings/power/qcom-rpmpd.h>
|
||||
|
||||
mdss@5e00000 {
|
||||
display-subsystem@5e00000 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
compatible = "qcom,sm6115-mdss";
|
||||
|
||||
@@ -2099,7 +2099,7 @@ int amdgpu_amdkfd_map_gtt_bo_to_gart(struct amdgpu_device *adev, struct amdgpu_b
|
||||
}
|
||||
|
||||
amdgpu_amdkfd_remove_eviction_fence(
|
||||
bo, bo->kfd_bo->process_info->eviction_fence);
|
||||
bo, bo->vm_bo->vm->process_info->eviction_fence);
|
||||
|
||||
amdgpu_bo_unreserve(bo);
|
||||
|
||||
|
||||
@@ -61,6 +61,8 @@ static int amdgpu_cs_parser_init(struct amdgpu_cs_parser *p,
|
||||
amdgpu_ctx_put(p->ctx);
|
||||
return -ECANCELED;
|
||||
}
|
||||
|
||||
amdgpu_sync_create(&p->sync);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -452,18 +454,6 @@ static int amdgpu_syncobj_lookup_and_add(struct amdgpu_cs_parser *p,
|
||||
}
|
||||
|
||||
r = amdgpu_sync_fence(&p->sync, fence);
|
||||
if (r)
|
||||
goto error;
|
||||
|
||||
/*
|
||||
* When we have an explicit dependency it might be necessary to insert a
|
||||
* pipeline sync to make sure that all caches etc are flushed and the
|
||||
* next job actually sees the results from the previous one.
|
||||
*/
|
||||
if (fence->context == p->gang_leader->base.entity->fence_context)
|
||||
r = amdgpu_sync_fence(&p->gang_leader->explicit_sync, fence);
|
||||
|
||||
error:
|
||||
dma_fence_put(fence);
|
||||
return r;
|
||||
}
|
||||
@@ -1188,10 +1178,19 @@ static int amdgpu_cs_vm_handling(struct amdgpu_cs_parser *p)
|
||||
static int amdgpu_cs_sync_rings(struct amdgpu_cs_parser *p)
|
||||
{
|
||||
struct amdgpu_fpriv *fpriv = p->filp->driver_priv;
|
||||
struct drm_gpu_scheduler *sched;
|
||||
struct amdgpu_bo_list_entry *e;
|
||||
struct dma_fence *fence;
|
||||
unsigned int i;
|
||||
int r;
|
||||
|
||||
r = amdgpu_ctx_wait_prev_fence(p->ctx, p->entities[p->gang_leader_idx]);
|
||||
if (r) {
|
||||
if (r != -ERESTARTSYS)
|
||||
DRM_ERROR("amdgpu_ctx_wait_prev_fence failed.\n");
|
||||
return r;
|
||||
}
|
||||
|
||||
list_for_each_entry(e, &p->validated, tv.head) {
|
||||
struct amdgpu_bo *bo = ttm_to_amdgpu_bo(e->tv.bo);
|
||||
struct dma_resv *resv = bo->tbo.base.resv;
|
||||
@@ -1211,10 +1210,24 @@ static int amdgpu_cs_sync_rings(struct amdgpu_cs_parser *p)
|
||||
return r;
|
||||
}
|
||||
|
||||
r = amdgpu_ctx_wait_prev_fence(p->ctx, p->entities[p->gang_leader_idx]);
|
||||
if (r && r != -ERESTARTSYS)
|
||||
DRM_ERROR("amdgpu_ctx_wait_prev_fence failed.\n");
|
||||
return r;
|
||||
sched = p->gang_leader->base.entity->rq->sched;
|
||||
while ((fence = amdgpu_sync_get_fence(&p->sync))) {
|
||||
struct drm_sched_fence *s_fence = to_drm_sched_fence(fence);
|
||||
|
||||
/*
|
||||
* When we have an dependency it might be necessary to insert a
|
||||
* pipeline sync to make sure that all caches etc are flushed and the
|
||||
* next job actually sees the results from the previous one
|
||||
* before we start executing on the same scheduler ring.
|
||||
*/
|
||||
if (!s_fence || s_fence->sched != sched)
|
||||
continue;
|
||||
|
||||
r = amdgpu_sync_fence(&p->gang_leader->explicit_sync, fence);
|
||||
if (r)
|
||||
return r;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void amdgpu_cs_post_dependencies(struct amdgpu_cs_parser *p)
|
||||
@@ -1254,9 +1267,12 @@ static int amdgpu_cs_submit(struct amdgpu_cs_parser *p,
|
||||
continue;
|
||||
|
||||
fence = &p->jobs[i]->base.s_fence->scheduled;
|
||||
dma_fence_get(fence);
|
||||
r = drm_sched_job_add_dependency(&leader->base, fence);
|
||||
if (r)
|
||||
if (r) {
|
||||
dma_fence_put(fence);
|
||||
goto error_cleanup;
|
||||
}
|
||||
}
|
||||
|
||||
if (p->gang_size > 1) {
|
||||
@@ -1344,6 +1360,7 @@ static void amdgpu_cs_parser_fini(struct amdgpu_cs_parser *parser)
|
||||
{
|
||||
unsigned i;
|
||||
|
||||
amdgpu_sync_free(&parser->sync);
|
||||
for (i = 0; i < parser->num_post_deps; i++) {
|
||||
drm_syncobj_put(parser->post_deps[i].syncobj);
|
||||
kfree(parser->post_deps[i].chain);
|
||||
|
||||
@@ -36,6 +36,7 @@
|
||||
#include <generated/utsrelease.h>
|
||||
#include <linux/pci-p2pdma.h>
|
||||
|
||||
#include <drm/drm_aperture.h>
|
||||
#include <drm/drm_atomic_helper.h>
|
||||
#include <drm/drm_fb_helper.h>
|
||||
#include <drm/drm_probe_helper.h>
|
||||
@@ -90,6 +91,8 @@ MODULE_FIRMWARE("amdgpu/navi12_gpu_info.bin");
|
||||
#define AMDGPU_MAX_RETRY_LIMIT 2
|
||||
#define AMDGPU_RETRY_SRIOV_RESET(r) ((r) == -EBUSY || (r) == -ETIMEDOUT || (r) == -EINVAL)
|
||||
|
||||
static const struct drm_driver amdgpu_kms_driver;
|
||||
|
||||
const char *amdgpu_asic_name[] = {
|
||||
"TAHITI",
|
||||
"PITCAIRN",
|
||||
@@ -3687,6 +3690,11 @@ int amdgpu_device_init(struct amdgpu_device *adev,
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
/* Get rid of things like offb */
|
||||
r = drm_aperture_remove_conflicting_pci_framebuffers(adev->pdev, &amdgpu_kms_driver);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
/* Enable TMZ based on IP_VERSION */
|
||||
amdgpu_gmc_tmz_set(adev);
|
||||
|
||||
|
||||
@@ -23,7 +23,6 @@
|
||||
*/
|
||||
|
||||
#include <drm/amdgpu_drm.h>
|
||||
#include <drm/drm_aperture.h>
|
||||
#include <drm/drm_drv.h>
|
||||
#include <drm/drm_fbdev_generic.h>
|
||||
#include <drm/drm_gem.h>
|
||||
@@ -2122,11 +2121,6 @@ static int amdgpu_pci_probe(struct pci_dev *pdev,
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Get rid of things like offb */
|
||||
ret = drm_aperture_remove_conflicting_pci_framebuffers(pdev, &amdgpu_kms_driver);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
adev = devm_drm_dev_alloc(&pdev->dev, &amdgpu_kms_driver, typeof(*adev), ddev);
|
||||
if (IS_ERR(adev))
|
||||
return PTR_ERR(adev);
|
||||
|
||||
@@ -470,8 +470,9 @@ static bool amdgpu_bo_validate_size(struct amdgpu_device *adev,
|
||||
return true;
|
||||
|
||||
fail:
|
||||
DRM_DEBUG("BO size %lu > total memory in domain: %llu\n", size,
|
||||
man->size);
|
||||
if (man)
|
||||
DRM_DEBUG("BO size %lu > total memory in domain: %llu\n", size,
|
||||
man->size);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -391,8 +391,10 @@ int amdgpu_sync_push_to_job(struct amdgpu_sync *sync, struct amdgpu_job *job)
|
||||
|
||||
dma_fence_get(f);
|
||||
r = drm_sched_job_add_dependency(&job->base, f);
|
||||
if (r)
|
||||
if (r) {
|
||||
dma_fence_put(f);
|
||||
return r;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -882,7 +882,7 @@ void amdgpu_vram_mgr_fini(struct amdgpu_device *adev)
|
||||
kfree(rsv);
|
||||
|
||||
list_for_each_entry_safe(rsv, temp, &mgr->reserved_pages, blocks) {
|
||||
drm_buddy_free_list(&mgr->mm, &rsv->blocks);
|
||||
drm_buddy_free_list(&mgr->mm, &rsv->allocated);
|
||||
kfree(rsv);
|
||||
}
|
||||
drm_buddy_fini(&mgr->mm);
|
||||
|
||||
@@ -200,7 +200,7 @@ static int add_queue_mes(struct device_queue_manager *dqm, struct queue *q,
|
||||
queue_input.wptr_addr = (uint64_t)q->properties.write_ptr;
|
||||
|
||||
if (q->wptr_bo) {
|
||||
wptr_addr_off = (uint64_t)q->properties.write_ptr - (uint64_t)q->wptr_bo->kfd_bo->va;
|
||||
wptr_addr_off = (uint64_t)q->properties.write_ptr & (PAGE_SIZE - 1);
|
||||
queue_input.wptr_mc_addr = ((uint64_t)q->wptr_bo->tbo.resource->start << PAGE_SHIFT) + wptr_addr_off;
|
||||
}
|
||||
|
||||
|
||||
@@ -570,6 +570,15 @@ svm_range_vram_node_new(struct amdgpu_device *adev, struct svm_range *prange,
|
||||
goto reserve_bo_failed;
|
||||
}
|
||||
|
||||
if (clear) {
|
||||
r = amdgpu_bo_sync_wait(bo, AMDGPU_FENCE_OWNER_KFD, false);
|
||||
if (r) {
|
||||
pr_debug("failed %d to sync bo\n", r);
|
||||
amdgpu_bo_unreserve(bo);
|
||||
goto reserve_bo_failed;
|
||||
}
|
||||
}
|
||||
|
||||
r = dma_resv_reserve_fences(bo->tbo.base.resv, 1);
|
||||
if (r) {
|
||||
pr_debug("failed %d to reserve bo\n", r);
|
||||
|
||||
@@ -1261,7 +1261,8 @@ int smu_v13_0_set_fan_speed_rpm(struct smu_context *smu,
|
||||
uint32_t speed)
|
||||
{
|
||||
struct amdgpu_device *adev = smu->adev;
|
||||
uint32_t tach_period, crystal_clock_freq;
|
||||
uint32_t crystal_clock_freq = 2500;
|
||||
uint32_t tach_period;
|
||||
int ret;
|
||||
|
||||
if (!speed)
|
||||
@@ -1271,7 +1272,6 @@ int smu_v13_0_set_fan_speed_rpm(struct smu_context *smu,
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
crystal_clock_freq = amdgpu_asic_get_xclk(adev);
|
||||
tach_period = 60 * crystal_clock_freq * 10000 / (8 * speed);
|
||||
WREG32_SOC15(THM, 0, regCG_TACH_CTRL,
|
||||
REG_SET_FIELD(RREG32_SOC15(THM, 0, regCG_TACH_CTRL),
|
||||
@@ -2298,6 +2298,10 @@ bool smu_v13_0_baco_is_support(struct smu_context *smu)
|
||||
!smu_baco->platform_support)
|
||||
return false;
|
||||
|
||||
/* return true if ASIC is in BACO state already */
|
||||
if (smu_v13_0_baco_get_state(smu) == SMU_BACO_STATE_ENTER)
|
||||
return true;
|
||||
|
||||
if (smu_cmn_feature_is_supported(smu, SMU_FEATURE_BACO_BIT) &&
|
||||
!smu_cmn_feature_is_enabled(smu, SMU_FEATURE_BACO_BIT))
|
||||
return false;
|
||||
|
||||
@@ -213,6 +213,7 @@ static struct cmn2asic_mapping smu_v13_0_0_feature_mask_map[SMU_FEATURE_COUNT] =
|
||||
FEA_MAP(SOC_PCC),
|
||||
[SMU_FEATURE_DPM_VCLK_BIT] = {1, FEATURE_MM_DPM_BIT},
|
||||
[SMU_FEATURE_DPM_DCLK_BIT] = {1, FEATURE_MM_DPM_BIT},
|
||||
[SMU_FEATURE_PPT_BIT] = {1, FEATURE_THROTTLERS_BIT},
|
||||
};
|
||||
|
||||
static struct cmn2asic_mapping smu_v13_0_0_table_map[SMU_TABLE_COUNT] = {
|
||||
|
||||
@@ -192,6 +192,7 @@ static struct cmn2asic_mapping smu_v13_0_7_feature_mask_map[SMU_FEATURE_COUNT] =
|
||||
FEA_MAP(SOC_PCC),
|
||||
[SMU_FEATURE_DPM_VCLK_BIT] = {1, FEATURE_MM_DPM_BIT},
|
||||
[SMU_FEATURE_DPM_DCLK_BIT] = {1, FEATURE_MM_DPM_BIT},
|
||||
[SMU_FEATURE_PPT_BIT] = {1, FEATURE_THROTTLERS_BIT},
|
||||
};
|
||||
|
||||
static struct cmn2asic_mapping smu_v13_0_7_table_map[SMU_TABLE_COUNT] = {
|
||||
|
||||
@@ -38,6 +38,25 @@ static void drm_block_free(struct drm_buddy *mm,
|
||||
kmem_cache_free(slab_blocks, block);
|
||||
}
|
||||
|
||||
static void list_insert_sorted(struct drm_buddy *mm,
|
||||
struct drm_buddy_block *block)
|
||||
{
|
||||
struct drm_buddy_block *node;
|
||||
struct list_head *head;
|
||||
|
||||
head = &mm->free_list[drm_buddy_block_order(block)];
|
||||
if (list_empty(head)) {
|
||||
list_add(&block->link, head);
|
||||
return;
|
||||
}
|
||||
|
||||
list_for_each_entry(node, head, link)
|
||||
if (drm_buddy_block_offset(block) < drm_buddy_block_offset(node))
|
||||
break;
|
||||
|
||||
__list_add(&block->link, node->link.prev, &node->link);
|
||||
}
|
||||
|
||||
static void mark_allocated(struct drm_buddy_block *block)
|
||||
{
|
||||
block->header &= ~DRM_BUDDY_HEADER_STATE;
|
||||
@@ -52,8 +71,7 @@ static void mark_free(struct drm_buddy *mm,
|
||||
block->header &= ~DRM_BUDDY_HEADER_STATE;
|
||||
block->header |= DRM_BUDDY_FREE;
|
||||
|
||||
list_add(&block->link,
|
||||
&mm->free_list[drm_buddy_block_order(block)]);
|
||||
list_insert_sorted(mm, block);
|
||||
}
|
||||
|
||||
static void mark_split(struct drm_buddy_block *block)
|
||||
@@ -387,20 +405,26 @@ err_undo:
|
||||
}
|
||||
|
||||
static struct drm_buddy_block *
|
||||
get_maxblock(struct list_head *head)
|
||||
get_maxblock(struct drm_buddy *mm, unsigned int order)
|
||||
{
|
||||
struct drm_buddy_block *max_block = NULL, *node;
|
||||
unsigned int i;
|
||||
|
||||
max_block = list_first_entry_or_null(head,
|
||||
struct drm_buddy_block,
|
||||
link);
|
||||
if (!max_block)
|
||||
return NULL;
|
||||
for (i = order; i <= mm->max_order; ++i) {
|
||||
if (!list_empty(&mm->free_list[i])) {
|
||||
node = list_last_entry(&mm->free_list[i],
|
||||
struct drm_buddy_block,
|
||||
link);
|
||||
if (!max_block) {
|
||||
max_block = node;
|
||||
continue;
|
||||
}
|
||||
|
||||
list_for_each_entry(node, head, link) {
|
||||
if (drm_buddy_block_offset(node) >
|
||||
drm_buddy_block_offset(max_block))
|
||||
max_block = node;
|
||||
if (drm_buddy_block_offset(node) >
|
||||
drm_buddy_block_offset(max_block)) {
|
||||
max_block = node;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return max_block;
|
||||
@@ -412,20 +436,23 @@ alloc_from_freelist(struct drm_buddy *mm,
|
||||
unsigned long flags)
|
||||
{
|
||||
struct drm_buddy_block *block = NULL;
|
||||
unsigned int i;
|
||||
unsigned int tmp;
|
||||
int err;
|
||||
|
||||
for (i = order; i <= mm->max_order; ++i) {
|
||||
if (flags & DRM_BUDDY_TOPDOWN_ALLOCATION) {
|
||||
block = get_maxblock(&mm->free_list[i]);
|
||||
if (block)
|
||||
break;
|
||||
} else {
|
||||
block = list_first_entry_or_null(&mm->free_list[i],
|
||||
struct drm_buddy_block,
|
||||
link);
|
||||
if (block)
|
||||
break;
|
||||
if (flags & DRM_BUDDY_TOPDOWN_ALLOCATION) {
|
||||
block = get_maxblock(mm, order);
|
||||
if (block)
|
||||
/* Store the obtained block order */
|
||||
tmp = drm_buddy_block_order(block);
|
||||
} else {
|
||||
for (tmp = order; tmp <= mm->max_order; ++tmp) {
|
||||
if (!list_empty(&mm->free_list[tmp])) {
|
||||
block = list_last_entry(&mm->free_list[tmp],
|
||||
struct drm_buddy_block,
|
||||
link);
|
||||
if (block)
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -434,18 +461,18 @@ alloc_from_freelist(struct drm_buddy *mm,
|
||||
|
||||
BUG_ON(!drm_buddy_block_is_free(block));
|
||||
|
||||
while (i != order) {
|
||||
while (tmp != order) {
|
||||
err = split_block(mm, block);
|
||||
if (unlikely(err))
|
||||
goto err_undo;
|
||||
|
||||
block = block->right;
|
||||
i--;
|
||||
tmp--;
|
||||
}
|
||||
return block;
|
||||
|
||||
err_undo:
|
||||
if (i != order)
|
||||
if (tmp != order)
|
||||
__drm_buddy_free(mm, block);
|
||||
return ERR_PTR(err);
|
||||
}
|
||||
|
||||
@@ -304,6 +304,12 @@ static const struct dmi_system_id orientation_data[] = {
|
||||
DMI_EXACT_MATCH(DMI_PRODUCT_VERSION, "Lenovo ideapad D330-10IGM"),
|
||||
},
|
||||
.driver_data = (void *)&lcd1200x1920_rightside_up,
|
||||
}, { /* Lenovo Ideapad D330-10IGL (HD) */
|
||||
.matches = {
|
||||
DMI_EXACT_MATCH(DMI_SYS_VENDOR, "LENOVO"),
|
||||
DMI_EXACT_MATCH(DMI_PRODUCT_VERSION, "Lenovo ideapad D330-10IGL"),
|
||||
},
|
||||
.driver_data = (void *)&lcd800x1280_rightside_up,
|
||||
}, { /* Lenovo Yoga Book X90F / X91F / X91L */
|
||||
.matches = {
|
||||
/* Non exact match to match all versions */
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user