/* * * Intel Integrated Touch Gfx Interface Layer * Copyright (c) 2016 Intel Corporation. * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, * version 2, as published by the Free Software Foundation. * * This program is distributed in the hope it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * */ #include #include #include #include "ipts.h" #include "ipts-msg-handler.h" #include "ipts-state.h" static void gfx_processing_complete(void *data) { ipts_info_t *ipts = data; if (ipts_get_state(ipts) == IPTS_STA_RAW_DATA_STARTED) { schedule_work(&ipts->raw_data_work); return; } ipts_dbg(ipts, "not ready to handle gfx event\n"); } static void notify_gfx_status(u32 status, void *data) { ipts_info_t *ipts = data; ipts_state_t state; ipts_dbg(ipts, "notify gfx status : %d\n", status); state = ipts_get_state(ipts); if (state == IPTS_STA_RAW_DATA_STARTED || state == IPTS_STA_HID_STARTED) { if (status == IPTS_NOTIFY_STA_BACKLIGHT_ON && ipts->display_status == false) { ipts_send_sensor_clear_mem_window_cmd(ipts); ipts->display_status = true; } else if (status == IPTS_NOTIFY_STA_BACKLIGHT_OFF && ipts->display_status == true) { ipts_send_sensor_quiesce_io_cmd(ipts); ipts->display_status = false; } } } static int connect_gfx(ipts_info_t *ipts) { int ret = 0; intel_ipts_connect_t ipts_connect; ipts_connect.if_version = IPTS_INTERFACE_V1; ipts_connect.ipts_cb.workload_complete = gfx_processing_complete; ipts_connect.ipts_cb.notify_gfx_status = notify_gfx_status; ipts_connect.data = (void*)ipts; ret = intel_ipts_connect(&ipts_connect); if (ret) return ret; /* TODO: gfx version check */ ipts->gfx_info.gfx_handle = ipts_connect.gfx_handle; ipts->gfx_info.ipts_ops = ipts_connect.ipts_ops; return ret; } static void disconnect_gfx(ipts_info_t *ipts) { intel_ipts_disconnect(ipts->gfx_info.gfx_handle); } #ifdef RUN_DBG_THREAD #include "../mei/mei_dev.h" static void ipts_print_dbg_info(ipts_info_t* ipts) { char fw_sts_str[MEI_FW_STATUS_STR_SZ]; u32 *db, *head, *tail; intel_ipts_wq_info_t* wq_info; wq_info = &ipts->resource.wq_info; mei_fw_status_str(ipts->cldev->bus, fw_sts_str, MEI_FW_STATUS_STR_SZ); pr_info(">> tdt : fw status : %s\n", fw_sts_str); db = (u32*)wq_info->db_addr; head = (u32*)wq_info->wq_head_addr; tail = (u32*)wq_info->wq_tail_addr; pr_info(">> == DB s:%x, c:%x ==\n", *db, *(db+1)); pr_info(">> == WQ h:%u, t:%u ==\n", *head, *tail); } static int ipts_dbg_thread(void *data) { ipts_info_t *ipts = (ipts_info_t*)data; pr_info(">> start debug thread\n"); while (1) { if (ipts_get_state(ipts) != IPTS_STA_RAW_DATA_STARTED) { pr_info("state is not IPTS_STA_RAW_DATA_SATARTED\n"); msleep(5000); continue; } ipts_print_dbg_info(ipts); msleep(3000); } return 0; } #endif int ipts_open_gpu(ipts_info_t *ipts) { int ret = 0; ret = connect_gfx(ipts); if (ret) { ipts_dbg(ipts, "cannot connect GPU\n"); return ret; } ret = ipts->gfx_info.ipts_ops.get_wq_info(ipts->gfx_info.gfx_handle, &ipts->resource.wq_info); if (ret) { ipts_dbg(ipts, "error in get_wq_info\n"); return ret; } #ifdef RUN_DBG_THREAD kthread_run(ipts_dbg_thread, (void*)ipts, "ipts_debug"); #endif return 0; } void ipts_close_gpu(ipts_info_t *ipts) { disconnect_gfx(ipts); } intel_ipts_mapbuffer_t *ipts_map_buffer(ipts_info_t *ipts, u32 size, u32 flags) { intel_ipts_mapbuffer_t *buf; u64 handle; int ret; buf = devm_kzalloc(&ipts->cldev->dev, sizeof(*buf), GFP_KERNEL); if (!buf) return NULL; buf->size = size; buf->flags = flags; handle = ipts->gfx_info.gfx_handle; ret = ipts->gfx_info.ipts_ops.map_buffer(handle, buf); if (ret) { devm_kfree(&ipts->cldev->dev, buf); return NULL; } return buf; } void ipts_unmap_buffer(ipts_info_t *ipts, intel_ipts_mapbuffer_t *buf) { u64 handle; int ret; if (!buf) return; handle = ipts->gfx_info.gfx_handle; ret = ipts->gfx_info.ipts_ops.unmap_buffer(handle, buf->buf_handle); devm_kfree(&ipts->cldev->dev, buf); }