diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c
index 6cd1c87eb1877..04b979e1501d2 100644
--- a/drivers/input/touchscreen/atmel_mxt_ts.c
+++ b/drivers/input/touchscreen/atmel_mxt_ts.c
@@ -75,6 +75,7 @@
 #define MXT_SPT_CTECONFIG_T46		46
 #define MXT_SPT_DYNAMICCONFIGURATIONCONTAINER_T71 71
 #define MXT_TOUCH_MULTITOUCHSCREEN_T100 100
+#define MXT_SPT_WIDGET_T152		152
 
 /* MXT_GEN_MESSAGE_T5 object */
 #define MXT_RPTID_NOMSG		0xff
@@ -186,6 +187,22 @@ enum t100_type {
 	MXT_T100_TYPE_LARGE_TOUCH	= 6,
 };
 
+/* T152 Message Types */
+#define MXT_BUTTON_KNOB		0x02
+#define MXT_POSITION_KNOB	0x03
+
+/* T152 Widget Object */
+#define MXT_T152_MAXDETENT	0x0a
+
+/* T152 Knob masks */
+#define MXT_KNOB_TYPE_MASK	0x07
+#define MXT_KNOB_EVENT_MASK	0x07
+
+/* T152 Position Events */
+#define MXT_POS_PUSH_MOVE	0x03
+#define MXT_POS_PUSH		0x04
+#define MXT_POS_UNPUSH		0x06
+
 #define MXT_DISTANCE_ACTIVE_TOUCH	0
 #define MXT_DISTANCE_HOVERING		1
 
@@ -336,6 +353,10 @@ struct mxt_data {
 	u8 T97_reportid_max;
 	u8 T100_reportid_min;
 	u8 T100_reportid_max;
+	u16 T152_address;
+	u8 T152_reportid_min;
+	u8 T152_reportid_max;
+	u8 T152_obj_size;
 
 	/* for fw update in bootloader */
 	struct completion bl_completion;
@@ -1026,6 +1047,41 @@ static void mxt_proc_t100_message(struct mxt_data *data, u8 *message)
 	data->update_input = true;
 }
 
+static void mxt_proc_t152_messages(struct mxt_data *data, u8 *message)
+{
+	struct input_dev *input_dev = data->input_dev;
+	int id = message[0] - data->T152_reportid_min;
+	u8 msg_type = message[1] & MXT_KNOB_TYPE_MASK;
+	u16 state;
+
+	if (msg_type == MXT_BUTTON_KNOB) {
+		state = get_unaligned_le16(&message[5]);
+		input_report_key(data->input_dev, BTN_0, !!(state & BIT(0)));
+		input_report_key(data->input_dev, BTN_1, !!(state & BIT(1)));
+		input_sync(data->input_dev);
+	} else if (msg_type == MXT_POSITION_KNOB) {
+		input_mt_report_slot_state(input_dev, MT_TOOL_DIAL, 1);
+
+		input_report_abs(input_dev, id ? ABS_GAS : ABS_WHEEL,
+				 get_unaligned_le16(&message[5]));
+		input_report_abs(input_dev, ABS_PRESSURE, message[8]);
+
+		/* Knob turn CCW is 0xffff or -1 , CW is 1 */
+		input_report_rel(input_dev, id ? REL_HWHEEL : REL_WHEEL,
+				 (s16)get_unaligned_le16(&message[3]));
+
+		state = message[2] & MXT_KNOB_EVENT_MASK;
+		if (state == MXT_POS_PUSH || state == MXT_POS_PUSH_MOVE)
+			input_report_key(input_dev, id ? BTN_B : BTN_A, 1);
+		else if (state == MXT_POS_UNPUSH)
+			input_report_key(input_dev, id ? BTN_B : BTN_A, 0);
+
+		input_mt_report_slot_inactive(input_dev);
+
+		input_sync(input_dev);
+	}
+}
+
 static int mxt_proc_message(struct mxt_data *data, u8 *message)
 {
 	u8 report_id = message[0];
@@ -1053,6 +1109,9 @@ static int mxt_proc_message(struct mxt_data *data, u8 *message)
 	} else if (report_id >= data->T100_reportid_min &&
 		   report_id <= data->T100_reportid_max) {
 		mxt_proc_t100_message(data, message);
+	} else if (report_id >= data->T152_reportid_min &&
+		   report_id <= data->T152_reportid_max) {
+		mxt_proc_t152_messages(data, message);
 	} else if (report_id == data->T19_reportid) {
 		mxt_input_button(data, message);
 		data->update_input = true;
@@ -1747,6 +1806,8 @@ static void mxt_free_object_table(struct mxt_data *data)
 	data->T97_reportid_max = 0;
 	data->T100_reportid_min = 0;
 	data->T100_reportid_max = 0;
+	data->T152_reportid_min = 0;
+	data->T152_reportid_max = 0;
 	data->max_reportid = 0;
 }
 
@@ -1841,6 +1902,12 @@ static int mxt_parse_object_table(struct mxt_data *data,
 			/* first two report IDs reserved */
 			data->num_touchids = object->num_report_ids - 2;
 			break;
+		case MXT_SPT_WIDGET_T152:
+			data->T152_address = object->start_address;
+			data->T152_reportid_min = min_id;
+			data->T152_reportid_max = max_id;
+			data->T152_obj_size = mxt_obj_size(object);
+			break;
 		}
 
 		end_address = object->start_address
@@ -2235,6 +2302,50 @@ static int mxt_initialize_input_device(struct mxt_data *data)
 					     EV_KEY, data->t15_keymap[i]);
 	}
 
+	/* For T152 knobs */
+	if (data->T152_address) {
+		u8 detent_ofs = data->T152_address + MXT_T152_MAXDETENT;
+		u8 bufp, bufs;
+
+		error = __mxt_read_reg(data->client, detent_ofs, 1, &bufp);
+		if (error)
+			goto err_free_mem;
+
+		error = __mxt_read_reg(data->client, detent_ofs + data->T152_obj_size,
+				       1, &bufs);
+		if (error)
+			goto err_free_mem;
+
+		if (bufp || bufs) {
+			input_set_abs_params(input_dev, ABS_MT_TOOL_TYPE,
+					     0, MT_TOOL_MAX, 0, 0);
+
+			/* Pressure reporting on both knobs */
+			input_set_capability(input_dev, EV_ABS, ABS_PRESSURE);
+			input_set_abs_params(input_dev, ABS_PRESSURE, 0, 255, 0, 0);
+		}
+
+		/* First knob */
+		if (bufp) {
+			input_set_capability(input_dev, EV_KEY, BTN_0);	/* Center */
+			input_set_capability(input_dev, EV_KEY, BTN_A);	/* Push */
+			input_set_capability(input_dev, EV_REL, REL_WHEEL);
+			input_set_capability(input_dev, EV_ABS, ABS_WHEEL);
+			input_set_abs_params(input_dev, ABS_WHEEL, 0, bufp - 1, 0, 0);
+			input_dev->relbit[0] |= BIT_MASK(REL_WHEEL);
+		}
+
+		/* Second knob */
+		if (bufs) {
+			input_set_capability(input_dev, EV_KEY, BTN_1);	/* Center */
+			input_set_capability(input_dev, EV_KEY, BTN_B);	/* Push */
+			input_set_capability(input_dev, EV_REL, REL_HWHEEL);
+			input_set_capability(input_dev, EV_ABS, ABS_GAS);
+			input_set_abs_params(input_dev, ABS_GAS, 0, bufs - 1, 0, 0);
+			input_dev->relbit[0] |= BIT_MASK(REL_HWHEEL);
+		}
+	}
+
 	input_set_drvdata(input_dev, data);
 
 	error = input_register_device(input_dev);
