A thread can give up control of CPU as it will generally wait on I/O, user input. Or it might be sleeping. So another thread can be selected to start running on the same CPU core. This is called voluntary context switch.
But sometimes the thread is doing some CPU intensive task & runs out of CPU time scheduled for it. Then process scheduler will take the thread out & add it back to the queue. It will then put next thread on the CPU. This is called involuntary context switch.
Hope this clarifies the difference in simple terms. I might write some more on involuntary context switches later.