summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNavneet Kumar <navneetk@nvidia.com>2017-03-28 16:50:43 -0400
committermobile promotions <svcmobile_promotions@nvidia.com>2017-03-30 20:34:31 -0400
commit5fbf460eef1fecd419509bcaa5a48f39aa3ea3e0 (patch)
tree643d7c7a9907da02fd5ac29a2cc6daf071c97fb3
parentf12c65d844d19c4b3422609dceda748388da51c3 (diff)
tegra: dc: fix fake panel state machine data
In fake panel support, the state machine caches dc contexts in a 2D array. This exposes a bug if a test switches between fake modes sequentially without falling back to original (non fake) mode before switching to the next fake mode. In the above scenario, coming back to the original mode (non fake) may lead to finding no cached dc context, hence causing a crash. go back to the old way of doing this, and have a 1D array to cache the contexts, getting rid of the unnecessary logic/compexity from 2D array. Bug 1883138 Change-Id: Ia3521b56b801cf00b0cc7e34047f40c8655f2cdd Signed-off-by: Navneet Kumar <navneetk@nvidia.com> Reviewed-on: http://git-master/r/1330141 Reviewed-by: mobile promotions <svcmobile_promotions@nvidia.com> Tested-by: mobile promotions <svcmobile_promotions@nvidia.com>
-rw-r--r--drivers/video/tegra/dc/dc.c51
1 files changed, 25 insertions, 26 deletions
diff --git a/drivers/video/tegra/dc/dc.c b/drivers/video/tegra/dc/dc.c
index 91fc96bb2..52508a9bd 100644
--- a/drivers/video/tegra/dc/dc.c
+++ b/drivers/video/tegra/dc/dc.c
@@ -1160,8 +1160,8 @@ struct tegra_dc_out_info {
1160 struct tegra_edid *edid; 1160 struct tegra_edid *edid;
1161}; 1161};
1162 1162
1163static struct tegra_dc_out_info dbg_dc_out_info[TEGRA_DC_OUT_MAX] 1163static struct tegra_dc_out_info dbg_dc_out_info[TEGRA_DC_OUT_MAX];
1164 [TEGRA_DC_OUT_MAX]; 1164
1165/* array for saving the out_type for each head */ 1165/* array for saving the out_type for each head */
1166static int boot_out_type[] = {-1, -1, -1}; 1166static int boot_out_type[] = {-1, -1, -1};
1167 1167
@@ -1216,7 +1216,7 @@ static int set_avdd(struct tegra_dc *dc, long cur_out, long new_out)
1216 */ 1216 */
1217 bool is_enable = false; 1217 bool is_enable = false;
1218 struct tegra_dc_out *dc_out = 1218 struct tegra_dc_out *dc_out =
1219 &dbg_dc_out_info[boot_out_type[dc->ndev->id]][new_out].out; 1219 &dbg_dc_out_info[boot_out_type[dc->ndev->id]].out;
1220 1220
1221 /* cur is fake and new is fake - skip */ 1221 /* cur is fake and new is fake - skip */
1222 if (is_valid_fake_support(dc, cur_out) && 1222 if (is_valid_fake_support(dc, cur_out) &&
@@ -1288,37 +1288,37 @@ static ssize_t dbg_dc_out_type_set(struct file *file,
1288 1288
1289 /* If output is already created - save it */ 1289 /* If output is already created - save it */
1290 if (dc->out_data) { 1290 if (dc->out_data) {
1291 dbg_dc_out_info[cur_dc_out][out_type].out_data = dc->out_data; 1291 dbg_dc_out_info[cur_dc_out].out_data = dc->out_data;
1292 dbg_dc_out_info[cur_dc_out][out_type].out_ops = dc->out_ops; 1292 dbg_dc_out_info[cur_dc_out].out_ops = dc->out_ops;
1293 memcpy(&dbg_dc_out_info[cur_dc_out][out_type].out, dc->out, 1293 memcpy(&dbg_dc_out_info[cur_dc_out].out, dc->out,
1294 sizeof(struct tegra_dc_out)); 1294 sizeof(struct tegra_dc_out));
1295 dbg_dc_out_info[cur_dc_out][out_type].mode = dc->mode; 1295 dbg_dc_out_info[cur_dc_out].mode = dc->mode;
1296 dbg_dc_out_info[cur_dc_out][out_type].edid = dc->edid; 1296 dbg_dc_out_info[cur_dc_out].edid = dc->edid;
1297 1297
1298 if (is_valid_dsi_out(dc, cur_dc_out) && 1298 if (is_valid_dsi_out(dc, cur_dc_out) &&
1299 dbg_dc_out_info[cur_dc_out][out_type].out_data) 1299 dbg_dc_out_info[cur_dc_out].out_data)
1300 tegra_dc_destroy_dsi_resources(dc, cur_dc_out); 1300 tegra_dc_destroy_dsi_resources(dc, cur_dc_out);
1301 1301
1302 if (!is_valid_fake_support(dc, cur_dc_out)) 1302 if (!is_valid_fake_support(dc, cur_dc_out))
1303 dbg_dc_out_info[cur_dc_out][out_type].fblistindex = 1303 dbg_dc_out_info[cur_dc_out].fblistindex =
1304 tegra_fb_update_modelist(dc, 0); 1304 tegra_fb_update_modelist(dc, 0);
1305 1305
1306 set_avdd(dc, cur_dc_out, out_type); 1306 set_avdd(dc, cur_dc_out, out_type);
1307 } 1307 }
1308 1308
1309 /* If output already created - reuse it */ 1309 /* If output already created - reuse it */
1310 if (dbg_dc_out_info[out_type][cur_dc_out].out_data) { 1310 if (dbg_dc_out_info[out_type].out_data) {
1311 mutex_lock(&dc->lp_lock); 1311 mutex_lock(&dc->lp_lock);
1312 mutex_lock(&dc->lock); 1312 mutex_lock(&dc->lock);
1313 1313
1314 /* Change the out type */ 1314 /* Change the out type */
1315 dc->pdata->default_out->type = out_type; 1315 dc->pdata->default_out->type = out_type;
1316 dc->out_ops = dbg_dc_out_info[out_type][cur_dc_out].out_ops; 1316 dc->out_ops = dbg_dc_out_info[out_type].out_ops;
1317 dc->out_data = dbg_dc_out_info[out_type][cur_dc_out].out_data; 1317 dc->out_data = dbg_dc_out_info[out_type].out_data;
1318 memcpy(dc->out, &dbg_dc_out_info[out_type][cur_dc_out].out, 1318 memcpy(dc->out, &dbg_dc_out_info[out_type].out,
1319 sizeof(struct tegra_dc_out)); 1319 sizeof(struct tegra_dc_out));
1320 dc->mode = dbg_dc_out_info[out_type][cur_dc_out].mode; 1320 dc->mode = dbg_dc_out_info[out_type].mode;
1321 dc->edid = dbg_dc_out_info[out_type][cur_dc_out].edid; 1321 dc->edid = dbg_dc_out_info[out_type].edid;
1322 1322
1323 /* Re-init the resources that are destroyed for dsi */ 1323 /* Re-init the resources that are destroyed for dsi */
1324 if (is_valid_dsi_out(dc, out_type)) 1324 if (is_valid_dsi_out(dc, out_type))
@@ -1326,8 +1326,7 @@ static ssize_t dbg_dc_out_type_set(struct file *file,
1326 1326
1327 if (!is_valid_fake_support(dc, out_type)) 1327 if (!is_valid_fake_support(dc, out_type))
1328 tegra_fb_update_modelist(dc, 1328 tegra_fb_update_modelist(dc,
1329 dbg_dc_out_info[out_type] 1329 dbg_dc_out_info[out_type].fblistindex);
1330 [cur_dc_out].fblistindex);
1331 1330
1332 mutex_unlock(&dc->lock); 1331 mutex_unlock(&dc->lock);
1333 mutex_unlock(&dc->lp_lock); 1332 mutex_unlock(&dc->lp_lock);
@@ -1370,15 +1369,15 @@ static ssize_t dbg_dc_out_type_set(struct file *file,
1370 tegra_dc_init_fakedsi_panel(dc, out_type); 1369 tegra_dc_init_fakedsi_panel(dc, out_type);
1371 1370
1372 } else if (out_type == TEGRA_DC_OUT_NULL) { 1371 } else if (out_type == TEGRA_DC_OUT_NULL) {
1373 if (!dbg_dc_out_info[TEGRA_DC_OUT_NULL] 1372 if (!dbg_dc_out_info[TEGRA_DC_OUT_NULL].out_data) {
1374 [cur_dc_out].out_data) {
1375 allocate = true; 1373 allocate = true;
1376 tegra_dc_init_null_or(dc); 1374 tegra_dc_init_null_or(dc);
1377 } 1375 }
1378 } else { 1376 } else {
1379 /* set back to existing one */ 1377 /* set back to existing one */
1380 dc->pdata->default_out->type = cur_dc_out; 1378 dc->pdata->default_out->type = cur_dc_out;
1381 dev_err(&dc->ndev->dev, "Unknown type is asked\n"); 1379 dev_err(&dc->ndev->dev, "Unknown type is asked: %ld\n",
1380 out_type);
1382 goto by_pass; 1381 goto by_pass;
1383 } 1382 }
1384 1383
@@ -1391,12 +1390,12 @@ static ssize_t dbg_dc_out_type_set(struct file *file,
1391 } 1390 }
1392 } 1391 }
1393 1392
1394 dbg_dc_out_info[out_type][cur_dc_out].out_ops = dc->out_ops; 1393 dbg_dc_out_info[out_type].out_ops = dc->out_ops;
1395 dbg_dc_out_info[out_type][cur_dc_out].out_data = dc->out_data; 1394 dbg_dc_out_info[out_type].out_data = dc->out_data;
1396 memcpy(&dbg_dc_out_info[out_type][cur_dc_out].out, dc->out, 1395 memcpy(&dbg_dc_out_info[out_type].out, dc->out,
1397 sizeof(struct tegra_dc_out)); 1396 sizeof(struct tegra_dc_out));
1398 dbg_dc_out_info[out_type][cur_dc_out].mode = dc->mode; 1397 dbg_dc_out_info[out_type].mode = dc->mode;
1399 dbg_dc_out_info[out_type][cur_dc_out].edid = dc->edid; 1398 dbg_dc_out_info[out_type].edid = dc->edid;
1400 1399
1401 } 1400 }
1402 1401